package org.richin.array.util;

import java.lang.reflect.Array;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.richin.collection.util.EmptyIterable;
import org.richin.collection.util.EmptyIterator;
import org.richin.lang.util.Convert;
import org.richin.lang.util.ObjectUtils;
import org.richin.lang.util.StringUtils;
import org.richin.system.util.Assert;

public class ArrayUtils {
	/* ============================================================================ */
	/*  常量和singleton。                                                           */
	/* ============================================================================ */

	/** 空的<code>Object</code>数组。 */
	public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

	/** 空的<code>Class</code>数组。 */
	public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

	/** 空的<code>String</code>数组。 */
	public static final String[] EMPTY_STRING_ARRAY = new String[0];

	/** 空的<code>long</code>数组。 */
	public static final long[] EMPTY_LONG_ARRAY = new long[0];

	/** 空的<code>Long</code>数组。 */
	public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];

	/** 空的<code>int</code>数组。 */
	public static final int[] EMPTY_INT_ARRAY = new int[0];

	/** 空的<code>Integer</code>数组。 */
	public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];

	/** 空的<code>short</code>数组。 */
	public static final short[] EMPTY_SHORT_ARRAY = new short[0];

	/** 空的<code>Short</code>数组。 */
	public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];

	/** 空的<code>byte</code>数组。 */
	public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];

	/** 空的<code>Byte</code>数组。 */
	public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];

	/** 空的<code>double</code>数组。 */
	public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];

	/** 空的<code>Double</code>数组。 */
	public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];

	/** 空的<code>float</code>数组。 */
	public static final float[] EMPTY_FLOAT_ARRAY = new float[0];

	/** 空的<code>Float</code>数组。 */
	public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];

	/** 空的<code>boolean</code>数组。 */
	public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];

	/** 空的<code>Boolean</code>数组。 */
	public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];

	/** 空的<code>char</code>数组。 */
	public static final char[] EMPTY_CHAR_ARRAY = new char[0];

	/** 空的<code>Character</code>数组。 */
	public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];

	/** 计算hashcode所用的常量。 */
	private static final int INITIAL_NON_ZERO_ODD_NUMBER = 17;

	/** 计算hashcode所用的常量。 */
	private static final int MULTIPLIER_NON_ZERO_ODD_NUMBER = 37;

	public static final int INDEX_NOT_FOUND = -1;

	/* ============================================================================ */
	/*  比较函数。                                                                  */
	/*                                                                              */
	/*  以下方法用来比较两个数组是否完全相同，支持多维数组。                        */
	/* ============================================================================ */

	/**
	 * 递归地比较两个数组是否相同，支持多维数组。
	 * 
	 * <p>
	 * 如果比较的对象不是数组，则此方法的结果同<code>ObjectUtil.equals</code>。
	 * </p>
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果相等, 则返回<code>true</code>
	 */
	public static boolean equals(Object array1, Object array2) {
		if (array1 == array2) {
			return true;
		}

		if ((array1 == null) || (array2 == null)) {
			return false;
		}

		Class clazz = array1.getClass();

		if (!clazz.equals(array2.getClass())) {
			return false;
		}

		if (!clazz.isArray()) {
			return array1.equals(array2);
		}

		// array1和array2为同类型的数组
		if (array1 instanceof long[]) {
			long[] longArray1 = (long[]) array1;
			long[] longArray2 = (long[]) array2;

			if (longArray1.length != longArray2.length) {
				return false;
			}

			for (int i = 0; i < longArray1.length; i++) {
				if (longArray1[i] != longArray2[i]) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof int[]) {
			int[] intArray1 = (int[]) array1;
			int[] intArray2 = (int[]) array2;

			if (intArray1.length != intArray2.length) {
				return false;
			}

			for (int i = 0; i < intArray1.length; i++) {
				if (intArray1[i] != intArray2[i]) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof short[]) {
			short[] shortArray1 = (short[]) array1;
			short[] shortArray2 = (short[]) array2;

			if (shortArray1.length != shortArray2.length) {
				return false;
			}

			for (int i = 0; i < shortArray1.length; i++) {
				if (shortArray1[i] != shortArray2[i]) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof byte[]) {
			byte[] byteArray1 = (byte[]) array1;
			byte[] byteArray2 = (byte[]) array2;

			if (byteArray1.length != byteArray2.length) {
				return false;
			}

			for (int i = 0; i < byteArray1.length; i++) {
				if (byteArray1[i] != byteArray2[i]) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof double[]) {
			double[] doubleArray1 = (double[]) array1;
			double[] doubleArray2 = (double[]) array2;

			if (doubleArray1.length != doubleArray2.length) {
				return false;
			}

			for (int i = 0; i < doubleArray1.length; i++) {
				if (Double.doubleToLongBits(doubleArray1[i]) != Double.doubleToLongBits(doubleArray2[i])) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof float[]) {
			float[] floatArray1 = (float[]) array1;
			float[] floatArray2 = (float[]) array2;

			if (floatArray1.length != floatArray2.length) {
				return false;
			}

			for (int i = 0; i < floatArray1.length; i++) {
				if (Float.floatToIntBits(floatArray1[i]) != Float.floatToIntBits(floatArray2[i])) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof boolean[]) {
			boolean[] booleanArray1 = (boolean[]) array1;
			boolean[] booleanArray2 = (boolean[]) array2;

			if (booleanArray1.length != booleanArray2.length) {
				return false;
			}

			for (int i = 0; i < booleanArray1.length; i++) {
				if (booleanArray1[i] != booleanArray2[i]) {
					return false;
				}
			}

			return true;
		} else if (array1 instanceof char[]) {
			char[] charArray1 = (char[]) array1;
			char[] charArray2 = (char[]) array2;

			if (charArray1.length != charArray2.length) {
				return false;
			}

			for (int i = 0; i < charArray1.length; i++) {
				if (charArray1[i] != charArray2[i]) {
					return false;
				}
			}

			return true;
		} else {
			Object[] objectArray1 = (Object[]) array1;
			Object[] objectArray2 = (Object[]) array2;

			if (objectArray1.length != objectArray2.length) {
				return false;
			}

			for (int i = 0; i < objectArray1.length; i++) {
				if (!equals(objectArray1[i], objectArray2[i])) {
					return false;
				}
			}

			return true;
		}
	}

	/**
	 * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
	 * correctly.</p>
	 * 
	 * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
	 * 
	 * @param array1  the left hand array to compare, may be <code>null</code>
	 * @param array2  the right hand array to compare, may be <code>null</code>
	 * @return <code>true</code> if the arrays are equal
	 */
	public static boolean isEquals(Object array1, Object array2) {
		return new EqualsBuilder().append(array1, array2).isEquals();
	}

	/* ============================================================================ */
	/*  将数组转换成集合类。                                                        */
	/* ============================================================================ */

	/**
	 * 将数组映射成固定长度的<code>List</code>，当改变这个<code>List</code>中的值时。数组中的相应值也被改变。
	 * 
	 * <p>
	 * 如果输入数组为<code>null</code>，则返回<code>null</code>。
	 * </p>
	 * 
	 * <p>
	 * 该方法内部调用<code>java.util.Arrays.asList</code>方法所返回的列表为指定数组的映像（固定长度），因此性能和内存占用上比<code>toList</code>方法更优。
	 * </p>
	 * 
	 * <p>
	 * 这个方法常被用于初始化，例如：
	 * <pre>
	 * List myList = ArrayUtil.toFixedList(new String[] { "aaa", "bbb", "ccc" });
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 *
	 * @return 以数组本身为映射的list
	 */
	public static List toFixedList(Object[] array) {
		if (array == null) {
			return null;
		}

		return Arrays.asList(array);
	}

	/**
	 * 将数组转换成<code>List</code>。
	 * 
	 * <p>
	 * 如果输入数组为<code>null</code>，则返回<code>null</code>。
	 * </p>
	 * 
	 * <p>
	 * 该方法返回的列表为指定数组的复本，而<code>java.util.Arrays.asList</code>方法所返回的列表为指定数组的映像（固定长度）。
	 * </p>
	 * 
	 * <p>
	 * 这个方法常被用于初始化，例如：
	 * <pre>
	 * List myList      = ArrayUtil.toList(new String[] { "aaa", "bbb", "ccc" });
	 * List singleList  = ArrayUtil.toList("hello");     // 返回单个元素的列表["hello"]
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 *
	 * @return 被创建的list
	 */
	public static List toList(Object array) {
		return toList(array, null);
	}

	/**
	 * 将数组转换成<code>List</code>。
	 * 
	 * <p>
	 * 如果输入数组为<code>null</code>，则返回<code>null</code>。
	 * </p>
	 * 
	 * <p>
	 * 该方法返回的列表为指定数组的复本，而<code>java.util.Arrays.asList</code>方法所返回的列表为指定数组的映像（固定长度）。
	 * </p>
	 * 
	 * <p>
	 * 这个方法常被用于初始化，例如：
	 * <pre>
	 * List myList      = ArrayUtil.toList(new String[] { "aaa", "bbb", "ccc" }, new ArrayList());
	 * List singleList  = ArrayUtil.toList("hello", new ArrayList());     // 返回单个元素的列表["hello"]
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 * @param list 要填充的列表，如果是<code>null</code>，则创建之
	 *
	 * @return 被创建或填充的list
	 */
	public static List toList(Object array, List list) {
		if (array == null) {
			return list;
		}

		// 非array，创建一个只有一个元素的列表
		if (!array.getClass().isArray()) {
			if (list == null) {
				list = new ArrayList(1);
			}

			list.add(array);
		} else if (array instanceof long[]) {
			long[] longArray = (long[]) array;

			if (list == null) {
				list = new ArrayList(longArray.length);
			}

			for (int i = 0; i < longArray.length; i++) {
				list.add(new Long(longArray[i]));
			}
		} else if (array instanceof int[]) {
			int[] intArray = (int[]) array;

			if (list == null) {
				list = new ArrayList(intArray.length);
			}

			for (int i = 0; i < intArray.length; i++) {
				list.add(new Integer(intArray[i]));
			}
		} else if (array instanceof short[]) {
			short[] shortArray = (short[]) array;

			if (list == null) {
				list = new ArrayList(shortArray.length);
			}

			for (int i = 0; i < shortArray.length; i++) {
				list.add(new Short(shortArray[i]));
			}
		} else if (array instanceof byte[]) {
			byte[] byteArray = (byte[]) array;

			if (list == null) {
				list = new ArrayList(byteArray.length);
			}

			for (int i = 0; i < byteArray.length; i++) {
				list.add(new Byte(byteArray[i]));
			}
		} else if (array instanceof double[]) {
			double[] doubleArray = (double[]) array;

			if (list == null) {
				list = new ArrayList(doubleArray.length);
			}

			for (int i = 0; i < doubleArray.length; i++) {
				list.add(new Double(doubleArray[i]));
			}
		} else if (array instanceof float[]) {
			float[] floatArray = (float[]) array;

			if (list == null) {
				list = new ArrayList(floatArray.length);
			}

			for (int i = 0; i < floatArray.length; i++) {
				list.add(new Float(floatArray[i]));
			}
		} else if (array instanceof boolean[]) {
			boolean[] booleanArray = (boolean[]) array;

			if (list == null) {
				list = new ArrayList(booleanArray.length);
			}

			for (int i = 0; i < booleanArray.length; i++) {
				list.add(booleanArray[i] ? Boolean.TRUE : Boolean.FALSE);
			}
		} else if (array instanceof char[]) {
			char[] charArray = (char[]) array;

			if (list == null) {
				list = new ArrayList(charArray.length);
			}

			for (int i = 0; i < charArray.length; i++) {
				list.add(new Character(charArray[i]));
			}
		} else {
			Object[] objectArray = (Object[]) array;

			if (list == null) {
				list = new ArrayList(objectArray.length);
			}

			for (int i = 0; i < objectArray.length; i++) {
				list.add(objectArray[i]);
			}
		}

		return list;
	}

	/**
	 * 将数组转换成<code>Map</code>。数组的元素必须是<code>Map.Entry</code>或元素个数多于2的子数组。
	 * 
	 * <p>
	 * 如果输入数组为<code>null</code>，则返回<code>null</code>。
	 * </p>
	 * 
	 * <p>
	 * 这个方法常被用于初始化，例如：
	 * <pre>
	 * Map colorMap = ArrayUtil.toMap(new String[][] {
	 *     {"RED", "#FF0000"},
	 *     {"GREEN", "#00FF00"},
	 *     {"BLUE", "#0000FF"}});
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 *
	 * @return 被创建的map
	 *
	 * @throws IllegalArgumentException 如果有一个子数组元素个数小于2或不是<code>Map.Entry</code>实例
	 */
	public static Map toMap(Object[] array) {
		return toMap(array, null);
	}

	/**
	 * 将数组转换成<code>Map</code>。数组的元素必须是<code>Map.Entry</code>或元素个数多于2的子数组。
	 * 
	 * <p>
	 * 如果输入数组为<code>null</code>，则返回<code>null</code>。
	 * </p>
	 * 
	 * <p>
	 * 这个方法常被用于初始化，例如：
	 * <pre>
	 * Map colorMap = ArrayUtil.toMap(new String[][] {{
	 *     {"RED", "#FF0000"},
	 *     {"GREEN", "#00FF00"},
	 *     {"BLUE", "#0000FF"}}, new HashMap());
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 * @param map 要填充的map，如果为<code>null</code>则自动创建之
	 *
	 * @return 被创建或填充的map
	 *
	 * @throws IllegalArgumentException 如果有一个子数组元素个数小于2或不是<code>Map.Entry</code>实例
	 */
	public static Map toMap(Object[] array, Map map) {
		if (array == null) {
			return map;
		}

		if (map == null) {
			map = new HashMap((int) (array.length * 1.5));
		}

		for (int i = 0; i < array.length; i++) {
			Object object = array[i];

			if (object instanceof Map.Entry) {
				Map.Entry entry = (Map.Entry) object;

				map.put(entry.getKey(), entry.getValue());
			} else if (object instanceof Object[]) {
				Object[] entry = (Object[]) object;

				if (entry.length < 2) {
					throw new IllegalArgumentException("Array element " + i + ", '" + object
							+ "', has a length less than 2");
				}

				map.put(entry[0], entry[1]);
			} else {
				throw new IllegalArgumentException("Array element " + i + ", '" + object
						+ "', is neither of type Map.Entry nor an Array");
			}
		}

		return map;
	}

	/* ============================================================================ */
	/*  比较数组的长度。                                                            */
	/* ============================================================================ */

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(Object[] array1, Object[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(long[] array1, long[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(int[] array1, int[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(short[] array1, short[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(byte[] array1, byte[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(double[] array1, double[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(float[] array1, float[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(boolean[] array1, boolean[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/**
	 * 判断两个数组是否具有相同的长度。如果数组为<code>null</code>则被看作长度为<code>0</code>。
	 *
	 * @param array1 数组1
	 * @param array2 数组2
	 *
	 * @return 如果两个数组长度相同，则返回<code>true</code>
	 */
	public static boolean isSameLength(char[] array1, char[] array2) {
		int length1 = (array1 == null) ? 0 : array1.length;
		int length2 = (array2 == null) ? 0 : array2.length;

		return length1 == length2;
	}

	/* ============================================================================ */
	/*  判空函数。                                                                  */
	/*                                                                              */
	/*  判断一个数组是否为null或包含0个元素。                                       */
	/* ============================================================================ */

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new String[0])     = true
	 * ArrayUtil.isEmpty(new String[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(Object[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new long[0])     = true
	 * ArrayUtil.isEmpty(new long[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(long[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new int[0])     = true
	 * ArrayUtil.isEmpty(new int[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(int[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new short[0])     = true
	 * ArrayUtil.isEmpty(new short[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(short[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new byte[0])     = true
	 * ArrayUtil.isEmpty(new byte[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(byte[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new double[0])     = true
	 * ArrayUtil.isEmpty(new double[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(double[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new float[0])     = true
	 * ArrayUtil.isEmpty(new float[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(float[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new boolean[0])     = true
	 * ArrayUtil.isEmpty(new boolean[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(boolean[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否为<code>null</code>或空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = true
	 * ArrayUtil.isEmpty(new char[0])     = true
	 * ArrayUtil.isEmpty(new char[10])    = false
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果为空, 则返回<code>true</code>
	 */
	public static boolean isEmpty(char[] array) {
		return ((array == null) || (array.length == 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new String[0])     = false
	 * ArrayUtil.isEmpty(new String[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(Object[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new long[0])     = false
	 * ArrayUtil.isEmpty(new long[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(long[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new int[0])     = false
	 * ArrayUtil.isEmpty(new int[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(int[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new short[0])     = false
	 * ArrayUtil.isEmpty(new short[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(short[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new byte[0])     = false
	 * ArrayUtil.isEmpty(new byte[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(byte[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new double[0])     = false
	 * ArrayUtil.isEmpty(new double[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(double[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new float[0])     = false
	 * ArrayUtil.isEmpty(new float[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(float[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new boolean[0])     = false
	 * ArrayUtil.isEmpty(new boolean[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(boolean[] array) {
		return ((array != null) && (array.length > 0));
	}

	/**
	 * 检查数组是否不是<code>null</code>和空数组<code>[]</code>。
	 * <pre>
	 * ArrayUtil.isEmpty(null)              = false
	 * ArrayUtil.isEmpty(new char[0])     = false
	 * ArrayUtil.isEmpty(new char[10])    = true
	 * </pre>
	 *
	 * @param array 要检查的数组
	 *
	 * @return 如果不为空, 则返回<code>true</code>
	 */
	public static boolean isNotEmpty(char[] array) {
		return ((array != null) && (array.length > 0));
	}

	public static <T> int sizeOf(T[] p_array) {
		if (p_array == null) {
			return 0;
		}
		return p_array.length;
	}

	public static int sizeOf(int[] p_array) {
		if (p_array == null) {
			return 0;
		}
		return p_array.length;
	}

	public static <T> T last(T[] p_array) throws Exception {
		int size = sizeOf(p_array);
		if (size == 0) {
			throw new Exception("Array must not be null or empty.");
		}
		return p_array[size - 1];
	}

	public static int last(int[] p_array) throws Exception {
		int size = sizeOf(p_array);
		if (size == 0) {
			throw new Exception("Array must not be null or empty.");
		}
		return p_array[size - 1];
	}

	public static <T> T first(T[] p_array) throws IllegalArgumentException {
		if (sizeOf(p_array) == 0) {
			throw new IllegalArgumentException("Array must not be null or empty.");
		}
		return p_array[0];
	}

	public static int first(int[] p_array) throws IllegalArgumentException {
		if (sizeOf(p_array) == 0) {
			throw new IllegalArgumentException("Array must not be null or empty.");
		}
		return p_array[0];
	}

	/**
	* Combines two arrays of parameters into one by concatenating the two, treating
	* null arrays as zero-length arrays.
	*
	* @param p_array1 the first array.
	* @param p_array2 the second array.
	*
	* @return a non-null array that combines the two arrays by concatenation.
	*/
	public static Object[] concat(Object[] p_array1, Object[] p_array2) {
		int size1 = sizeOf(p_array1);
		int size2 = sizeOf(p_array2);

		Object[] result = new Object[size1 + size2];

		if (size1 > 0) {
			System.arraycopy(p_array1, 0, result, 0, size1);
		}
		if (size2 > 0) {
			System.arraycopy(p_array2, 0, result, size1, size2);
		}
		return result;
	}

	/**
	* Returns the <code>Iterable</code> for the specified array, or an empty
	* <code>Iterable</code> if the array is <code>null</code>, to avoid
	* <code>NullPointerException</code>s.
	*/
	public static <T> Iterable<T> iterable(T[] p_array) {
		if (p_array == null) {
			return new EmptyIterable<T>();
		}
		return Arrays.asList(p_array);
	}

	/**
	 * Returns the {@link java.util.Iterator} for the specified array, or an empty
	 * iterator if the array is <code>null</code>, to avoid
	 * <code>NullPointerException</code>s.
	 */
	public static <T> Iterator<T> iterator(T[] p_array) {
		if (p_array == null) {
			return new EmptyIterator<T>();
		}
		return new ArrayIterator<T>(p_array);
	}

	/**
	 * 获取对象在数组中的位置
	 * 
	 * @param obj
	 *            Object
	 * @param source
	 *            Object[]
	 * @return int
	 */
	public static int indexOf(Object obj, Object[] source) {
		int index = -1;
		if (null != source && 0 < source.length) {
			for (int i = 0; i < source.length; i++) {
				if (obj.equals(source[i])) {
					index = i;
					break;
				}
			}
		}
		return index;
	}

	public static <T> int indexOfT(final T[] array, final T value, final int startIndex) {
		final int alen = array.length;
		for (int i = startIndex; i < alen; i++) {
			if (value.equals(array[i])) {
				return i;
			}
		}
		return INDEX_NOT_FOUND;
	}

	/* ============================================================================ */
	/*  反转数组的元素顺序。                                                        */
	/* ============================================================================ */

	/**
	 * 反转数组的元素顺序。如果数组为<code>null</code>，则什么也不做。
	 *
	 * @param array 要反转的数组
	 */
	public static void reverse(Object[] array) {
		if (array == null) {
			return;
		}

		Object tmp;

		for (int i = 0, j = array.length - 1; j > i; i++, j--) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
		}
	}

	/**
	 * 反转数组的元素顺序。如果数组为<code>null</code>，则什么也不做。
	 *
	 * @param array 要反转的数组
	 */
	public static void reverse(long[] array) {
		if (array == null) {
			return;
		}

		long tmp;

		for (int i = 0, j = array.length - 1; j > i; i++, j--) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
		}
	}

	/**
	 * 反转数组的元素顺序。如果数组为<code>null</code>，则什么也不做。
	 *
	 * @param array 要反转的数组
	 */
	public static void reverse(int[] array) {
		if (array == null) {
			return;
		}

		int tmp;

		for (int i = 0, j = array.length - 1; j > i; i++, j--) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
		}
		/*       int i = 0;
		       int j = array.length - 1;
		       while(j > i) {
		           tmp = array[j];
		           array[j] = array[i];
		           array[i] = tmp;
		           j--;
		           i++;
		       }*/
	}

	public static int[] reverseTo(final int[] ary) {
		if (ary == null) {
			return null;
		}
		int[] b = new int[ary.length];
		for (int i = 0; i < ary.length; i++) {
			b[ary.length - i - 1] = ary[i];
		}
		return b;
	}

	public static boolean startsWith(final byte[] target, final byte[] prefix) {
		final int testlen = prefix.length;
		if (target.length < testlen) {
			return false;
		}
		for (int i = 0; i < testlen; i++) {
			if (target[i] != prefix[i]) {
				return false;
			}
		}
		return true;
	}

	public static int compareTo(final byte lhs[], final byte rhs[]) {
		if (lhs == rhs) {
			return 0;
		}
		final int len = Math.min(lhs.length, rhs.length);
		for (int i = 0; i < len; i++) {
			if (lhs[i] != rhs[i]) {
				return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
			}
		}
		return lhs.length - rhs.length;
	}

	public static int compareTo(final byte lhs[], final byte rhs[], final int offset) {
		final int len = Math.min(lhs.length, rhs.length);
		for (int i = offset; i < len; i++) {
			if (lhs[i] != rhs[i]) {
				return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
			}
		}
		return lhs.length - rhs.length;
	}

	public static int compareTo(final byte lhs[], final byte rhs[], final int offset, final int length) {
		int tolen = offset + length;
		final int limit = Math.min(Math.min(lhs.length, rhs.length), tolen);
		for (int i = offset; i < limit; i++) {
			if (lhs[i] != rhs[i]) {
				return (lhs[i] & 0xFF) - (rhs[i] & 0xFF);
			}
		}
		return 0;
	}

	public static int compare(final byte[] b1, final int off1, final int len1, final byte[] b2, final int off2,
			final int len2) {
		for (int i = 0; i < len1 && i < len2; i++) {
			final int d = (b1[off1 + i] & 0xFF) - (b2[off2 + i] & 0xFF);
			if (d != 0) {
				return d;
			}
		}
		return len1 - len2;
	}

	public static <T> boolean containsWithEquals(final T[] array, final T value) {
		final int len = array.length;
		for (int i = 0; i < len; i++) {
			if (array[i].equals(value)) {
				return true;
			}
		}
		return false;
	}

	public static int longestCommonPrefix(final byte[] ary, final byte[] root) {
		final int limit = Math.min(ary.length, root.length);
		for (int i = 0; i < limit; i++) {
			if (ary[i] != root[i]) {
				return i;
			}
		}
		return limit;
	}

	public static void shuffle(final Object[] array) {
		final Random r = new Random();
		final int limit = array.length;
		for (int i = 0; i < limit; ++i) {
			swap(array, i, r.nextInt(limit));
		}
	}

	public static void shuffle(final int[] array) {
		final Random r = new Random();
		final int limit = array.length;
		for (int i = 0; i < limit; ++i) {
			swap(array, i, r.nextInt(limit));
		}
	}

	public static void shuffle(final Object[] array, final long seed) {
		final Random r = new Random(seed);
		final int limit = array.length;
		for (int i = 0; i < limit; ++i) {
			swap(array, i, r.nextInt(limit));
		}
	}

	public static <T> T max(final T[] array, final double[] scores) {
		if (array.length != scores.length) {
			throw new IllegalArgumentException("array.length(" + array.length + ") != scores.length(" + scores.length
					+ ")");
		}
		T obj = null;
		double d = Double.MIN_VALUE;
		for (int i = 0; i < scores.length; i++) {
			final double score = scores[i];
			if (score > d) {
				d = score;
				obj = array[i];
			}
		}
		return obj;
	}

	public static int minIndex(final float[] scores) {
		int index = -1;
		float min = Float.MAX_VALUE;
		for (int i = 0; i < scores.length; i++) {
			final float f = scores[i];
			if (f < min) {
				min = f;
				index = i;
			}
		}
		return index;
	}

	@SuppressWarnings("unchecked")
	public static <T> Class<T[]> getArrayClass(Class<T> clazz) {
		Object array = Array.newInstance(clazz, 0);
		return (Class<T[]>) array.getClass();
	}

	public static <T> Set<T> asSet(T[] array) {
		final Set<T> set = new HashSet<T>(array.length);
		for (T e : array) {
			set.add(e);
		}
		return set;
	}

	/**
	 * ArrayUtils.toArray(list, String[].class)
	 * @param <T>
	 * @param c
	 * @param newType
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] toArray(final Collection<T> c, final Class<? extends T[]> newType) {
		final int length = c.size();
		final T[] array = (T[]) Array.newInstance(newType.getComponentType(), length);
		if (length > 0) {
			int i = 0;
			for (T elem : c) {
				array[i++] = elem;
			}
		}
		return array;
	}//

	public static void swap(final Object[] array, final int i, final int j) {
		Object o = array[i];
		array[i] = array[j];
		array[j] = o;
	}

	public static void swap(final int[] array, final int i, final int j) {
		int o = array[i];
		array[i] = array[j];
		array[j] = o;
	}

	public static double max(final double[] array) {
		double d = Double.MIN_VALUE;
		for (int i = 0; i < array.length; i++) {
			d = Math.max(array[i], d);
		}
		return d;
	}

	/**
	 * 反转数组的元素顺序。如果数组为<code>null</code>，则什么也不做。
	 *
	 * @param array 要反转的数组
	 */
	public static void reverse(byte[] array) {
		if (array == null) {
			return;
		}

		byte tmp;

		for (int i = 0, j = array.length - 1; j > i; i++, j--) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
		}
	}

	/**
	* 反转数组的元素顺序。如果数组为<code>null</code>，则什么也不做。
	*
	* @param array 要反转的数组
	*/
	public static void reverse(char[] array) {
		if (array == null) {
			return;
		}

		char tmp;

		for (int i = 0, j = array.length - 1; j > i; i++, j--) {
			tmp = array[j];
			array[j] = array[i];
			array[i] = tmp;
		}
	}

	/* ============================================================================ */
	/*  在数组中查找一个元素或一个元素序列。                                        */
	/*                                                                              */
	/*  类型：Object[]                                                              */
	/* ============================================================================ */

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param objectToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(Object[] array, Object objectToFind) {
		return indexOf(array, objectToFind, 0);
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(Object[] array, Object[] arrayToFind) {
		return indexOf(array, arrayToFind, 0);
	}

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param objectToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (objectToFind == null) {
			for (int i = startIndex; i < array.length; i++) {
				if (array[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = startIndex; i < array.length; i++) {
				if (objectToFind.equals(array[i])) {
					return i;
				}
			}
		}

		return -1;
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(Object[] array, Object[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		if (startIndex >= sourceLength) {
			return (targetLength == 0) ? sourceLength : (-1);
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		Object first = arrayToFind[0];
		int i = startIndex;
		int max = sourceLength - targetLength;

		startSearchForFirst: while (true) {
			// 查找第一个元素
			while ((i <= max) && !ObjectUtils.equals(array[i], first)) {
				i++;
			}

			if (i > max) {
				return -1;
			}

			// 已经找到第一个元素，接着找
			int j = i + 1;
			int end = (j + targetLength) - 1;
			int k = 1;

			while (j < end) {
				if (!ObjectUtils.equals(array[j++], arrayToFind[k++])) {
					i++;

					// 重新查找第一个元素
					continue startSearchForFirst;
				}
			}

			// 找到了
			return i;
		}
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param objectToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(Object[] array, Object objectToFind) {
		return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
	}

	/**
	 * Returns the last index of the given array or -1 if empty or null.
	 * This method can deal with <code>Object</code> arrays and with primitive arrays.
	 * This value is one less than the size since arrays indices are 0-based.</p>
	 *
	 * <pre>
	 * ArrayUtils.lastIndex(null)            = -1
	 * ArrayUtils.lastIndex([])              = -1
	 * ArrayUtils.lastIndex([null])          = 0
	 * ArrayUtils.lastIndex([true, false])   = 1
	 * ArrayUtils.lastIndex([1, 2, 3])       = 2
	 * ArrayUtils.lastIndex(["a", "b", "c"]) = 2
	 * </pre>
	 *
	 * @param array  the array to return the last index for, may be null
	 * @return the last index, -1 if empty or null
	 * @throws IllegalArgumentException if the object arguement is not an array.
	 */
	public static int lastIndex(final Object array) {
		return ArrayUtils.getLength(array) - 1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(Object[] array, Object[] arrayToFind) {
		return lastIndexOf(array, arrayToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param objectToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			return -1;
		} else if (startIndex >= array.length) {
			startIndex = array.length - 1;
		}

		if (objectToFind == null) {
			for (int i = startIndex; i >= 0; i--) {
				if (array[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = startIndex; i >= 0; i--) {
				if (objectToFind.equals(array[i])) {
					return i;
				}
			}
		}

		return -1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(Object[] array, Object[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		int rightIndex = sourceLength - targetLength;

		if (startIndex < 0) {
			return -1;
		}

		if (startIndex > rightIndex) {
			startIndex = rightIndex;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int lastIndex = targetLength - 1;
		Object last = arrayToFind[lastIndex];
		int min = targetLength - 1;
		int i = min + startIndex;

		startSearchForLast: while (true) {
			while ((i >= min) && !ObjectUtils.equals(array[i], last)) {
				i--;
			}

			if (i < min) {
				return -1;
			}

			int j = i - 1;
			int start = j - (targetLength - 1);
			int k = lastIndex - 1;

			while (j > start) {
				if (!ObjectUtils.equals(array[j--], arrayToFind[k--])) {
					i--;
					continue startSearchForLast;
				}
			}

			return start + 1;
		}
	}

	/**
	 * 判断指定对象是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param objectToFind 要查找的元素
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(Object[] array, Object objectToFind) {
		return indexOf(array, objectToFind) != -1;
	}

	public static String[] fillArray(String value, int length) {
		String[] result = new String[length];
		Arrays.fill(result, value);
		return result;
	}

	public static int[] fillArray(int value, int length) {
		int[] result = new int[length];
		Arrays.fill(result, value);
		return result;
	}

	public static String[] toStringArray(Collection<?> coll) {
		return (String[]) coll.toArray(EMPTY_STRING_ARRAY);
	}

	public static int[] toIntArray(Collection<?> coll) {
		Iterator<?> iter = coll.iterator();
		int[] arr = new int[coll.size()];
		int i = 0;
		while (iter.hasNext()) {
			arr[i++] = ((Integer) iter.next()).intValue();
		}
		return arr;
	}

	public static boolean[] toBooleanArray(Collection<?> coll) {
		Iterator<?> iter = coll.iterator();
		boolean[] arr = new boolean[coll.size()];
		int i = 0;
		while (iter.hasNext()) {
			arr[i++] = ((Boolean) iter.next()).booleanValue();
		}
		return arr;
	}

	public static String[] slice(String[] strings, int begin, int length) {
		String[] result = new String[length];
		for (int i = 0; i < length; i++) {
			result[i] = strings[begin + i];
		}
		return result;
	}

	public static Object[] slice(Object[] objects, int begin, int length) {
		Object[] result = new Object[length];
		for (int i = 0; i < length; i++) {
			result[i] = objects[begin + i];
		}
		return result;
	}

	public static String[] join(String[] x, String[] y) {
		String[] result = new String[x.length + y.length];
		for (int i = 0; i < x.length; i++)
			result[i] = x[i];
		for (int i = 0; i < y.length; i++)
			result[i + x.length] = y[i];
		return result;
	}

	public static String[] join(String[] x, String[] y, boolean[] use) {
		String[] result = new String[x.length + countTrue(use)];
		for (int i = 0; i < x.length; i++)
			result[i] = x[i];
		int k = x.length;
		for (int i = 0; i < y.length; i++) {
			if (use[i])
				result[k++] = y[i];
		}
		return result;
	}

	public static int[] join(int[] x, int[] y) {
		int[] result = new int[x.length + y.length];
		for (int i = 0; i < x.length; i++)
			result[i] = x[i];
		for (int i = 0; i < y.length; i++)
			result[i + x.length] = y[i];
		return result;
	}

	public static boolean isAllNegative(int[] array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i] >= 0)
				return false;
		}
		return true;
	}

	public static boolean isAllTrue(boolean[] array) {
		for (int i = 0; i < array.length; i++) {
			if (!array[i])
				return false;
		}
		return true;
	}

	public static int countTrue(boolean[] array) {
		int result = 0;
		for (int i = 0; i < array.length; i++) {
			if (array[i])
				result++;
		}
		return result;
	}

	public static int countFalse(boolean[] array) {
		int result = 0;
		for (int i = 0; i < array.length; i++) {
			if (!array[i])
				result++;
		}
		return result;
	}

	public static boolean isEquals(Object[] o1, Object[] o2) {
		if (o1 == o2)
			return true;
		if (o1 == null || o2 == null)
			return false;
		int length = o1.length;
		if (length != o2.length)
			return false;
		for (int index = 0; index < length; index++) {
			if (!o1[index].equals(o2[index]))
				return false;
		}
		return true;
	}

	public static boolean isEquals(char[] o1, char[] o2) {
		if (o1 == o2)
			return true;
		if (o1 == null || o2 == null)
			return false;
		int length = o1.length;
		if (length != o2.length)
			return false;
		for (int index = 0; index < length; index++) {
			if (!(o1[index] == o2[index]))
				return false;
		}
		return true;
	}

	public static boolean isEquals(byte[] b1, byte[] b2) {
		if (b1 == b2)
			return true;
		if (b1 == null || b2 == null)
			return false;
		int length = b1.length;
		if (length != b2.length)
			return false;
		for (int index = 0; index < length; index++) {
			if (!(b1[index] == b2[index]))
				return false;
		}
		return true;
	}

	public static String[] trimArrayElements(String[] array) {
		if (isEmpty(array)) {
			return new String[0];
		}
		String[] result = new String[array.length];
		for (int i = 0; i < array.length; i++) {
			String element = array[i];
			result[i] = (element != null ? element.trim() : null);
		}
		return result;
	}

	public static boolean isAllFalse(boolean[] array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i])
				return false;
		}
		return true;
	}

	public static Object[] typecast(Object[] array, Object[] to) {
		return java.util.Arrays.asList(array).toArray(to);
	}

	/**
	 * 判断指定元素序列是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(Object[] array, Object[] arrayToFind) {
		return indexOf(array, arrayToFind) != -1;
	}

	/* ============================================================================ */
	/*  在数组中查找一个元素或一个元素序列。                                        */
	/*                                                                              */
	/*  类型：long[]                                                                */
	/* ============================================================================ */

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param longToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(long[] array, long longToFind) {
		return indexOf(array, longToFind, 0);
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(long[] array, long[] arrayToFind) {
		return indexOf(array, arrayToFind, 0);
	}

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param longToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(long[] array, long longToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		for (int i = startIndex; i < array.length; i++) {
			if (longToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(long[] array, long[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		if (startIndex >= sourceLength) {
			return (targetLength == 0) ? sourceLength : (-1);
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		long first = arrayToFind[0];
		int i = startIndex;
		int max = sourceLength - targetLength;

		startSearchForFirst: while (true) {
			// 查找第一个元素
			while ((i <= max) && (array[i] != first)) {
				i++;
			}

			if (i > max) {
				return -1;
			}

			// 已经找到第一个元素，接着找
			int j = i + 1;
			int end = (j + targetLength) - 1;
			int k = 1;

			while (j < end) {
				if (array[j++] != arrayToFind[k++]) {
					i++;

					// 重新查找第一个元素
					continue startSearchForFirst;
				}
			}

			// 找到了
			return i;
		}
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param longToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(long[] array, long longToFind) {
		return lastIndexOf(array, longToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(long[] array, long[] arrayToFind) {
		return lastIndexOf(array, arrayToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param longToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(long[] array, long longToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			return -1;
		} else if (startIndex >= array.length) {
			startIndex = array.length - 1;
		}

		for (int i = startIndex; i >= 0; i--) {
			if (longToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(long[] array, long[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		int rightIndex = sourceLength - targetLength;

		if (startIndex < 0) {
			return -1;
		}

		if (startIndex > rightIndex) {
			startIndex = rightIndex;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int lastIndex = targetLength - 1;
		long last = arrayToFind[lastIndex];
		int min = targetLength - 1;
		int i = min + startIndex;

		startSearchForLast: while (true) {
			while ((i >= min) && (array[i] != last)) {
				i--;
			}

			if (i < min) {
				return -1;
			}

			int j = i - 1;
			int start = j - (targetLength - 1);
			int k = lastIndex - 1;

			while (j > start) {
				if (array[j--] != arrayToFind[k--]) {
					i--;
					continue startSearchForLast;
				}
			}

			return start + 1;
		}
	}

	/**
	 * 判断指定对象是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param longToFind 要查找的元素
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(long[] array, long longToFind) {
		return indexOf(array, longToFind) != -1;
	}

	/**
	 * 判断指定元素序列是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(long[] array, long[] arrayToFind) {
		return indexOf(array, arrayToFind) != -1;
	}

	/* ============================================================================ */
	/*  在数组中查找一个元素或一个元素序列。                                        */
	/*                                                                              */
	/*  类型：int[]                                                                 */
	/* ============================================================================ */

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param intToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(int[] array, int intToFind) {
		return indexOf(array, intToFind, 0);
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(int[] array, int[] arrayToFind) {
		return indexOf(array, arrayToFind, 0);
	}

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param intToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(int[] array, int intToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		for (int i = startIndex; i < array.length; i++) {
			if (intToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(int[] array, int[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		if (startIndex >= sourceLength) {
			return (targetLength == 0) ? sourceLength : (-1);
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int first = arrayToFind[0];
		int i = startIndex;
		int max = sourceLength - targetLength;

		startSearchForFirst: while (true) {
			// 查找第一个元素
			while ((i <= max) && (array[i] != first)) {
				i++;
			}

			if (i > max) {
				return -1;
			}

			// 已经找到第一个元素，接着找
			int j = i + 1;
			int end = (j + targetLength) - 1;
			int k = 1;

			while (j < end) {
				if (array[j++] != arrayToFind[k++]) {
					i++;

					// 重新查找第一个元素
					continue startSearchForFirst;
				}
			}

			// 找到了
			return i;
		}
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param intToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(int[] array, int intToFind) {
		return lastIndexOf(array, intToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(int[] array, int[] arrayToFind) {
		return lastIndexOf(array, arrayToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param intToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(int[] array, int intToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			return -1;
		} else if (startIndex >= array.length) {
			startIndex = array.length - 1;
		}

		for (int i = startIndex; i >= 0; i--) {
			if (intToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(int[] array, int[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		int rightIndex = sourceLength - targetLength;

		if (startIndex < 0) {
			return -1;
		}

		if (startIndex > rightIndex) {
			startIndex = rightIndex;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int lastIndex = targetLength - 1;
		int last = arrayToFind[lastIndex];
		int min = targetLength - 1;
		int i = min + startIndex;

		startSearchForLast: while (true) {
			while ((i >= min) && (array[i] != last)) {
				i--;
			}

			if (i < min) {
				return -1;
			}

			int j = i - 1;
			int start = j - (targetLength - 1);
			int k = lastIndex - 1;

			while (j > start) {
				if (array[j--] != arrayToFind[k--]) {
					i--;
					continue startSearchForLast;
				}
			}

			return start + 1;
		}
	}

	/**
	 * 判断指定对象是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param intToFind 要查找的元素
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(int[] array, int intToFind) {
		return indexOf(array, intToFind) != -1;
	}

	/**
	 * 判断指定元素序列是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(int[] array, int[] arrayToFind) {
		return indexOf(array, arrayToFind) != -1;
	}

	/* ============================================================================ */
	/*  在数组中查找一个元素或一个元素序列。                                        */
	/*                                                                              */
	/*  类型：char[]                                                                */
	/* ============================================================================ */

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param charToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(char[] array, char charToFind) {
		return indexOf(array, charToFind, 0);
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(char[] array, char[] arrayToFind) {
		return indexOf(array, arrayToFind, 0);
	}

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param charToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(char[] array, char charToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		for (int i = startIndex; i < array.length; i++) {
			if (charToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(char[] array, char[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		if (startIndex >= sourceLength) {
			return (targetLength == 0) ? sourceLength : (-1);
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		char first = arrayToFind[0];
		int i = startIndex;
		int max = sourceLength - targetLength;

		startSearchForFirst: while (true) {
			// 查找第一个元素
			while ((i <= max) && (array[i] != first)) {
				i++;
			}

			if (i > max) {
				return -1;
			}

			// 已经找到第一个元素，接着找
			int j = i + 1;
			int end = (j + targetLength) - 1;
			int k = 1;

			while (j < end) {
				if (array[j++] != arrayToFind[k++]) {
					i++;

					// 重新查找第一个元素
					continue startSearchForFirst;
				}
			}

			// 找到了
			return i;
		}
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param charToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(char[] array, char charToFind) {
		return lastIndexOf(array, charToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(char[] array, char[] arrayToFind) {
		return lastIndexOf(array, arrayToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param charToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(char[] array, char charToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			return -1;
		} else if (startIndex >= array.length) {
			startIndex = array.length - 1;
		}

		for (int i = startIndex; i >= 0; i--) {
			if (charToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(char[] array, char[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		int rightIndex = sourceLength - targetLength;

		if (startIndex < 0) {
			return -1;
		}

		if (startIndex > rightIndex) {
			startIndex = rightIndex;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int lastIndex = targetLength - 1;
		char last = arrayToFind[lastIndex];
		int min = targetLength - 1;
		int i = min + startIndex;

		startSearchForLast: while (true) {
			while ((i >= min) && (array[i] != last)) {
				i--;
			}

			if (i < min) {
				return -1;
			}

			int j = i - 1;
			int start = j - (targetLength - 1);
			int k = lastIndex - 1;

			while (j > start) {
				if (array[j--] != arrayToFind[k--]) {
					i--;
					continue startSearchForLast;
				}
			}

			return start + 1;
		}
	}

	/**
	 * 判断指定对象是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param charToFind 要查找的元素
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(char[] array, char charToFind) {
		return indexOf(array, charToFind) != -1;
	}

	/**
	 * 判断指定元素序列是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(char[] array, char[] arrayToFind) {
		return indexOf(array, arrayToFind) != -1;
	}

	/* ============================================================================ */
	/*  在数组中查找一个元素或一个元素序列。                                        */
	/*                                                                              */
	/*  类型：byte[]                                                                */
	/* ============================================================================ */

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param byteToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(byte[] array, byte byteToFind) {
		return indexOf(array, byteToFind, 0);
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(byte[] array, byte[] arrayToFind) {
		return indexOf(array, arrayToFind, 0);
	}

	/**
	 * 在数组中查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param byteToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(byte[] array, byte byteToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		for (int i = startIndex; i < array.length; i++) {
			if (byteToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则看作<code>0</code>，超出数组长度的起始索引则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int indexOf(byte[] array, byte[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		if (startIndex >= sourceLength) {
			return (targetLength == 0) ? sourceLength : (-1);
		}

		if (startIndex < 0) {
			startIndex = 0;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		byte first = arrayToFind[0];
		int i = startIndex;
		int max = sourceLength - targetLength;

		startSearchForFirst: while (true) {
			// 查找第一个元素
			while ((i <= max) && (array[i] != first)) {
				i++;
			}

			if (i > max) {
				return -1;
			}

			// 已经找到第一个元素，接着找
			int j = i + 1;
			int end = (j + targetLength) - 1;
			int k = 1;

			while (j < end) {
				if (array[j++] != arrayToFind[k++]) {
					i++;

					// 重新查找第一个元素
					continue startSearchForFirst;
				}
			}

			// 找到了
			return i;
		}
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param byteToFind 要查找的元素
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(byte[] array, byte byteToFind) {
		return lastIndexOf(array, byteToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(byte[] array, byte[] arrayToFind) {
		return lastIndexOf(array, arrayToFind, Integer.MAX_VALUE);
	}

	/**
	 * 在数组中从末尾开始查找一个元素。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param byteToFind 要查找的元素
	 * @param startIndex 起始索引
	 *
	 * @return 该元素在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(byte[] array, byte byteToFind, int startIndex) {
		if (array == null) {
			return -1;
		}

		if (startIndex < 0) {
			return -1;
		} else if (startIndex >= array.length) {
			startIndex = array.length - 1;
		}

		for (int i = startIndex; i >= 0; i--) {
			if (byteToFind == array[i]) {
				return i;
			}
		}

		return -1;
	}

	/**
	 * 在数组中从末尾开始查找一个元素序列。
	 * 
	 * <p>
	 * 如果未找到或数组为<code>null</code>则返回<code>-1</code>。
	 * </p>
	 * 
	 * <p>
	 * 起始索引小于<code>0</code>则返回<code>-1</code>，超出数组长度的起始索引则从数组末尾开始找。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 * @param startIndex 起始索引
	 *
	 * @return 该元素序列在数组中的序号，如果数组为<code>null</code>或未找到，则返回<code>-1</code>。
	 */
	public static int lastIndexOf(byte[] array, byte[] arrayToFind, int startIndex) {
		if ((array == null) || (arrayToFind == null)) {
			return -1;
		}

		int sourceLength = array.length;
		int targetLength = arrayToFind.length;

		int rightIndex = sourceLength - targetLength;

		if (startIndex < 0) {
			return -1;
		}

		if (startIndex > rightIndex) {
			startIndex = rightIndex;
		}

		if (targetLength == 0) {
			return startIndex;
		}

		int lastIndex = targetLength - 1;
		byte last = arrayToFind[lastIndex];
		int min = targetLength - 1;
		int i = min + startIndex;

		startSearchForLast: while (true) {
			while ((i >= min) && (array[i] != last)) {
				i--;
			}

			if (i < min) {
				return -1;
			}

			int j = i - 1;
			int start = j - (targetLength - 1);
			int k = lastIndex - 1;

			while (j > start) {
				if (array[j--] != arrayToFind[k--]) {
					i--;
					continue startSearchForLast;
				}
			}

			return start + 1;
		}
	}

	/**
	 * 判断指定对象是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param byteToFind 要查找的元素
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(byte[] array, byte byteToFind) {
		return indexOf(array, byteToFind) != -1;
	}

	/**
	 * 判断指定元素序列是否存在于指定数组中。
	 * 
	 * <p>
	 * 如果数组为<code>null</code>则返回<code>false</code>。
	 * </p>
	 *
	 * @param array 要扫描的数组
	 * @param arrayToFind 要查找的元素序列
	 *
	 * @return 如果找到则返回<code>true</code>
	 */
	public static boolean contains(byte[] array, byte[] arrayToFind) {
		return indexOf(array, arrayToFind) != -1;
	}

	/* ============================================================================ */
	/*  将数组转换成易于阅读的字符串表示。                                          */
	/*                                                                              */
	/*  支持多维数组。                                                              */
	/* ============================================================================ */

	/**
	 * 将数组转换成易于阅读的字符串表示。
	 * 
	 * <p>
	 * 如果数组是<code>null</code>则返回<code>[]</code>，支持多维数组。
	 * 如果数组元素为<code>null</code>，则显示<code>&lt;null&gt;</code>。
	 * <pre>
	 * ArrayUtil.toString(null)                              = "[]"
	 * ArrayUtil.toString(new int[] {1, 2, 3})               = "[1, 2, 3]"
	 * ArrayUtil.toString(new boolean[] {true, false, true}) = "[true, false, true]"
	 * ArrayUtil.toString(new Object[] {
	 *                       {1, 2, 3},  // 嵌套数组
	 *                       hello,      // 嵌套非数组
	 *                       null,       // 嵌套null
	 *                       {},         // 嵌套空数组
	 *                       {2, 3, 4}   // 嵌套数组
	 *                    })                                 = "[[1, 2, 3], hello, <null>, [], [2, 3, 4]]"
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 *
	 * @return 字符串表示，<code>"[]"</code>表示空数组或<code>null</code>
	 */
	public static String toString(Object array) {
		return toString(array, "[]", "<null>");
	}//System.out.println(toString(s));

	/**
	 * 将数组转换成易于阅读的字符串表示。
	 * 
	 * <p>
	 * 如果数组是<code>null</code>则返回指定字符串，支持多维数组。
	 * 如果数组元素为<code>null</code>，则显示<code>&lt;null&gt;</code>。
	 * <pre>
	 * ArrayUtil.toString(null, "null")                              = "null"
	 * ArrayUtil.toString(new int[] {1, 2, 3}, "null")               = "[1, 2, 3]"
	 * ArrayUtil.toString(new boolean[] {true, false, true}, "null") = "[true, false, true]"
	 * ArrayUtil.toString(new Object[] {
	 *                       {1, 2, 3},  // 嵌套数组
	 *                       hello,      // 嵌套非数组
	 *                       null,       // 嵌套null
	 *                       {},         // 嵌套空数组
	 *                       {2, 3, 4}   // 嵌套数组
	 *                    }, "null")                                 = "[[1, 2, 3], hello, <null>, [], [2, 3, 4]]"
	 * </pre>
	 * </p>
	 *
	 * @param array 要转换的数组
	 * @param nullArrayStr 如果数组是<code>null</code>，则返回此字符串
	 *
	 * @return 字符串表示，或返回指定字符串表示<code>null</code>
	 */
	public static String toString(Object array, String nullArrayStr) {
		return toString(array, nullArrayStr, "<null>");
	}

	/**
	* 将数组转换成易于阅读的字符串表示。
	* 
	* <p>
	* 如果数组是<code>null</code>则返回指定字符串，支持多维数组。 如果数组元素为<code>null</code>，则显示指定字符串。
	* <pre>
	* ArrayUtil.toString(null, "null", "NULL")                              = "null"
	* ArrayUtil.toString(new int[] {1, 2, 3}, "null", "NULL")               = "[1, 2, 3]"
	* ArrayUtil.toString(new boolean[] {true, false, true}, "null", "NULL") = "[true, false, true]"
	* ArrayUtil.toString(new Object[] {
	*                       {1, 2, 3},  // 嵌套数组
	*                       hello,      // 嵌套非数组
	*                       null,       // 嵌套null
	*                       {},         // 嵌套空数组
	*                       {2, 3, 4}   // 嵌套数组
	*                    }, "null", "NULL")                                 = "[[1, 2, 3], hello, NULL, [], [2, 3, 4]]"
	* </pre>
	* </p>
	*
	* @param array 要转换的数组
	* @param nullArrayStr 如果数组是<code>null</code>，则返回此字符串
	* @param nullElementStr 如果数组中的元素为<code>null</code>，则返回此字符串
	*
	* @return 字符串表示，或返回指定字符串表示<code>null</code>
	*/
	public static String toString(Object array, String nullArrayStr, String nullElementStr) {
		if (array == null) {
			return nullArrayStr;
		}

		StringBuffer buffer = new StringBuffer();

		toString(buffer, array, nullArrayStr, nullElementStr);

		return buffer.toString();
	}

	/**
	* 显示字符串数组的内容
	*
	* @param args
	*            字符串数组
	* @param separator
	*            分隔符
	* @return 字符串数组的内容
	*/
	public static String toString(String[] args, String separator) {
		if (isEmpty(args)) {
			return null;
		}
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < args.length; i++) {
			if (i > 0) {
				buffer.append(separator);
			}
			buffer.append(args[i]);
		}
		return buffer.toString();
	}

	/**
	 * 将数组转换成易于阅读的字符串表示。<code>null</code>将被看作空数组。 支持多维数组。
	 *
	 * @param buffer 将转换后的字符串加入到这个<code>StringBuffer</code>中
	 * @param array 要转换的数组
	 * @param nullArrayStr 如果数组是<code>null</code>，则返回此字符串
	 * @param nullElementStr 如果数组中的元素为<code>null</code>，则返回此字符串
	 */
	private static void toString(StringBuffer buffer, Object array, String nullArrayStr, String nullElementStr) {
		if (array == null) {
			buffer.append(nullElementStr);
			return;
		}

		if (!array.getClass().isArray()) {
			buffer.append(ObjectUtils.toString(array, nullElementStr));
			return;
		}

		buffer.append('[');

		// array为数组
		if (array instanceof long[]) {
			long[] longArray = (long[]) array;
			int length = longArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(longArray[i]);
			}
		} else if (array instanceof int[]) {
			int[] intArray = (int[]) array;
			int length = intArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(intArray[i]);
			}
		} else if (array instanceof short[]) {
			short[] shortArray = (short[]) array;
			int length = shortArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(shortArray[i]);
			}
		} else if (array instanceof byte[]) {
			byte[] byteArray = (byte[]) array;
			int length = byteArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				} else {
					buffer.append("0x");
				}

				String hexStr = Integer.toHexString(0xFF & byteArray[i]).toUpperCase();

				if (hexStr.length() == 0) {
					buffer.append("00");
				} else if (hexStr.length() == 1) {
					buffer.append("0");
				}

				buffer.append(hexStr);
			}
		} else if (array instanceof double[]) {
			double[] doubleArray = (double[]) array;
			int length = doubleArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(doubleArray[i]);
			}
		} else if (array instanceof float[]) {
			float[] floatArray = (float[]) array;
			int length = floatArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(floatArray[i]);
			}
		} else if (array instanceof boolean[]) {
			boolean[] booleanArray = (boolean[]) array;
			int length = booleanArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(booleanArray[i]);
			}
		} else if (array instanceof char[]) {
			char[] charArray = (char[]) array;
			int length = charArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				buffer.append(charArray[i]);
			}
		} else {
			Object[] objectArray = (Object[]) array;
			int length = objectArray.length;

			for (int i = 0; i < length; i++) {
				if (i > 0) {
					buffer.append(", ");
				}

				toString(buffer, objectArray[i], nullArrayStr, nullElementStr);
			}
		}

		buffer.append(']');
	}

	public static int[] add(int[] array, int value) {
		if (array == null) {
			return new int[] { value };
		} else {
			int[] tmp = new int[array.length + 1];
			System.arraycopy(array, 0, tmp, 0, array.length);
			tmp[array.length] = value;
			return tmp;
		}
	}

	public static Object[] add(Class componentType, Object[] array, Object value) {
		Object[] tmp;
		if (array == null) {
			tmp = (Object[]) java.lang.reflect.Array.newInstance(componentType, 1);
		} else {
			tmp = (Object[]) java.lang.reflect.Array.newInstance(componentType, array.length + 1);
			System.arraycopy(array, 0, tmp, 0, array.length);
		}
		tmp[tmp.length - 1] = value;
		return tmp;
	}

	public static Object[] insert(Object[] array, int index, int number) {
		if ((index < 0) || (index > array.length)) {
			throw new ArrayIndexOutOfBoundsException(index);
		}

		Object[] tmp = (Object[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length
				+ number);
		if (index > 0) {
			System.arraycopy(array, 0, tmp, 0, index);
		}
		if (index < array.length) {
			System.arraycopy(array, index, tmp, index + number, array.length - index);
		}
		return tmp;
	}

	public static Object[] insert(Class componentType, Object[] array, int index, int number) {
		int len = array == null ? 0 : array.length;
		if ((index < 0) || (index > len)) {
			throw new ArrayIndexOutOfBoundsException(index);
		}
		Object[] tmp = (Object[]) java.lang.reflect.Array.newInstance(componentType, len + number);
		if (index > 0) {
			System.arraycopy(array, 0, tmp, 0, index);
		}
		if (index < len) {
			System.arraycopy(array, index, tmp, index + number, array.length - index);
		}
		return tmp;
	}

	/**
	 * Removes the element at the specified index. If the array only contains
	 * one element (the removed one), <CODE>null</CODE> is returned.
	 *
	 * @param array the array to remove the element from
	 * @param index the index of the element to remove
	 * @return the array with the element removed or <CODE>null</CODE> if
	 *    the array no longer contains any elements.
	 */
	public static Object[] remove(Object[] array, int index) {
		// Check that the index is a valid index
		if ((index < 0) || (index >= array.length))
			throw new ArrayIndexOutOfBoundsException(index);

		if (array.length == 1)
			return null;

		Object[] tmp = (Object[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(),
				array.length - 1);
		if (index > 0) {
			System.arraycopy(array, 0, tmp, 0, index);
		}
		if (index < tmp.length) {
			System.arraycopy(array, index + 1, tmp, index, tmp.length - index);
		}
		return tmp;
	}

	public static Object[] remove(Object[] array, Object element) {
		int index = indexOf(array, element);
		return (index >= 0) ? remove(array, index) : array;
	}

	public static Object[] remove(Object[] array, int index, int number) {
		// Check that the index is a valid index
		if ((index < 0) || (index >= array.length)) {
			throw new ArrayIndexOutOfBoundsException(index);
		}

		if ((array.length - index) < number) {
			number = array.length - index;
		}

		if ((index == 0) && (array.length == number)) {
			return null;
		}

		Object[] tmp = (Object[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length
				- number);
		if (index > 0) {
			System.arraycopy(array, 0, tmp, 0, index);
		}
		if (index + number < array.length) {
			System.arraycopy(array, index + number, tmp, index, array.length - index - number);
		}
		return tmp;
	}

	/**
	 * <p>Removes the element at the specified position from the specified array.
	 * All subsequent elements are shifted to the left (substracts one from
	 * their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array except the element on the specified position. The component
	 * type of the returned array is always the same as that of the input
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, an IndexOutOfBoundsException
	 * will be thrown, because in that case no valid index can be specified.</p>
	 *
	 * @param array  the array to remove the element from, may not be <code>null</code>
	 * @param index  the position of the element to be removed
	 * @return A new array containing the existing elements except the element
	 *         at the specified position.
	 * @throws IndexOutOfBoundsException if the index is out of range
	 * (index < 0 || index >= array.length), or if the array is <code>null</code>.
	 * @since 2.1
	 */
	public static <T> T[] removeT(final T[] array, final int index) {
		int length = getLength(array);
		if (index < 0 || index >= length) {
			throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
		}
		Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
		System.arraycopy(array, 0, result, 0, index);
		if (index < length - 1) {
			System.arraycopy(array, index + 1, result, index, length - index - 1);
		}
		return (T[]) result;
	}

	public static <T> T[] removeT(final T[] array, final int from, final int to) {
		assert (to >= from) : to + " - " + from;
		int length = getLength(array);
		if (from < 0 || to >= length) {
			throw new IndexOutOfBoundsException("from: " + from + ", to: " + to + ", Length: " + length);
		}
		int remsize = to - from + 1;
		Object result = Array.newInstance(array.getClass().getComponentType(), length - remsize);
		System.arraycopy(array, 0, result, 0, from);
		if (to < length - 1) {
			System.arraycopy(array, to + 1, result, from, length - to - 1);
		}
		return (T[]) result;
	}

	/**
	 * Returns a copy of the given array of size 1 greater than the argument.
	 * The last value of the array is left to the default value.
	 *
	 * @param array The array to copy, must not be <code>null</code>.
	 * @param newArrayComponentType If <code>array</code> is <code>null</code>, create a
	 * size 1 array of this type.
	 * @return A new copy of the array of size 1 greater than the input.
	 */
	private static Object copyArrayGrow1(final Object array, final Class newArrayComponentType) {
		if (array != null) {
			int arrayLength = Array.getLength(array);
			Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
			System.arraycopy(array, 0, newArray, 0, arrayLength);
			return newArray;
		} else {
			return Array.newInstance(newArrayComponentType, 1);
		}
	}

	public static boolean equals(final char[] a, final char[] a2, final int off, final int len) {
		if (a == a2) {
			return true;
		}
		if (a == null || a2 == null) {
			return false;
		}
		int length = a.length;
		if (len != length) {
			return false;
		}
		for (int i = 0; i < len; i++) {
			if (a[i] != a2[off + i]) {
				return false;
			}
		}
		return true;
	}

	public static char[] copyOfRange(final char[] original, final int from, final int to) {
		final int newLength = to - from;
		if (newLength < 0) {
			throw new IllegalArgumentException(from + " > " + to);
		}
		final char[] copy = new char[newLength];
		System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
		return copy;
	}

	public static byte[] copyOfRange(final byte[] original, final int from, final int to) {
		final int newLength = to - from;
		if (newLength < 0) {
			throw new IllegalArgumentException(from + " > " + to);
		}
		final byte[] copy = new byte[newLength];
		System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
		return copy;
	}

	public static int[] copyOfRange(final int[] original, final int from, final int to) {
		final int newLength = to - from;
		if (newLength < 0) {
			throw new IllegalArgumentException(from + " > " + to);
		}
		final int[] copy = new int[newLength];
		System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
		return copy;
	}

	public static long[] copyOfRange(final long[] original, final int from, final int to) {
		final int newLength = to - from;
		if (newLength < 0) {
			throw new IllegalArgumentException(from + " > " + to);
		}
		final long[] copy = new long[newLength];
		System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
		return copy;
	}

	public static <T> T[] copyOfRange(final T[] original, final int from, final int to) {
		return copyOfRange(original, from, to, (Class<T[]>) original.getClass());
	}

	private static <T, U> T[] copyOfRange(final U[] original, final int from, final int to,
			final Class<? extends T[]> newType) {
		final int newLength = to - from;
		if (newLength < 0) {
			throw new IllegalArgumentException(from + " > " + to);
		}
		final T[] copy = ((Object) newType == (Object) Object[].class) ? (T[]) new Object[newLength] : (T[]) Array
				.newInstance(newType.getComponentType(), newLength);
		System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
		return copy;
	}

	public static byte[] copyOf(final byte[] original, final int newLength) {
		final byte[] copy = new byte[newLength];
		System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
		return copy;
	}

	public static int[] copyOf(final int[] original, final int newLength) {
		final int[] copy = new int[newLength];
		System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
		return copy;
	}

	public static char[] copyOf(final char[] original, final int newLength) {
		final char[] copy = new char[newLength];
		System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
		return copy;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] copyOf(T[] original, int newLength) {
		return (T[]) copyOf(original, newLength, original.getClass());
	}

	@SuppressWarnings("unchecked")
	public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
		final T[] copy = ((Object) newType == (Object) Object[].class) ? (T[]) new Object[newLength] : (T[]) Array
				.newInstance(newType.getComponentType(), newLength);
		System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
		return copy;
	}

	/**
	 * Sorts the array of values.
	 *
	 * @param values The array of values to sort.
	 * @parm first The value that should be placed in first position after
	 *       sorting
	 * @return The sorted array.
	 */
	public static String[] sort(String[] values, String first) {
		LinkedList<String> ll = new LinkedList<String>();
		for (String val : values)
			ll.add(val);

		Collections.sort(ll);
		// Remove first from the list and re-add in first position.
		ll.remove(first);
		ll.addFirst(first);

		String[] ret = new String[ll.size()];
		ll.toArray(ret);
		return ret;
	}

	/**
	 * For each field in fields, sorts the values in constrainedValues and
	 * places the value in fields at teh front of the sorted list. This is done
	 * for each field in the fields array and the result of which is returned as
	 * an ArrayList<String[]>.
	 *
	 * @param fields The fields that the constrainedValues should be sorted on.
	 * @param constrainedValues The subset of constrained values (should include
	 *            any values that are in the fields array)
	 * @return An ArrayList of sorted constrainedValues for each field.
	 */
	public static ArrayList<String[]> sortAndExpand(String[] fields, String[] constrainedValues) {
		ArrayList<String[]> ret = new ArrayList<String[]>();
		for (String metric : fields) {
			constrainedValues = sort(constrainedValues, metric);
			ret.add(constrainedValues);
		}
		return ret;
	}

	public static int binarySearch(final Object[] a, final int fromIndex, final int toIndex, final Object key) {
		int low = fromIndex;
		int high = toIndex - 1;

		while (low <= high) {
			int mid = (low + high) >>> 1;
			Comparable midVal = (Comparable) a[mid];
			int cmp = midVal.compareTo(key);

			if (cmp < 0) {
				low = mid + 1;
			} else if (cmp > 0) {
				high = mid - 1;
			} else {
				return mid; // key found
			}
		}
		return -(low + 1); // key not found.
	}

	public static long[] remove(final long[] vals, final int idx) {
		long[] newVals = new long[vals.length - 1];
		if (idx > 0) {
			System.arraycopy(vals, 0, newVals, 0, idx);
		}
		if (idx < newVals.length) {
			System.arraycopy(vals, idx + 1, newVals, idx, newVals.length - idx);
		}
		return newVals;
	}

	public static long[] remove(final long[] vals, final int from, final int to) {
		int remsize = to - from + 1;
		long[] newVals = new long[vals.length - remsize];
		if (from > 0) {
			System.arraycopy(vals, 0, newVals, 0, from);
		}
		if (to < newVals.length) {
			System.arraycopy(vals, to + 1, newVals, from, newVals.length - to);
		}
		return newVals;
	}

	public static Object[] setSize(Object[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		Object[] tmp = (Object[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), newSize);
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static char[] setSize(char[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		char[] tmp = new char[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static byte[] setSize(byte[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		byte[] tmp = new byte[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static float[] setSize(float[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		float[] tmp = new float[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static double[] setSize(double[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		double[] tmp = new double[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static boolean[] setSize(boolean[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		boolean[] tmp = new boolean[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static int[] setSize(int[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		int[] tmp = new int[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static long[] setSize(long[] array, int newSize) {
		if (array.length == newSize) {
			return array;
		}

		long[] tmp = new long[newSize];
		if (newSize > array.length) {
			System.arraycopy(array, 0, tmp, 0, array.length);
		} else {
			System.arraycopy(array, 0, tmp, 0, newSize);
		}
		return tmp;
	}

	public static String toString(Object[] array) {
		if (array == null) {
			return "null";
		} else {
			StringBuffer sb = new StringBuffer();
			sb.append(array.getClass().getComponentType().getName()).append('[');
			if (array.length > 0) {
				sb.append(array[0]);

				for (int i = 1; i < array.length; i++) {
					sb.append(',').append(array[i]);
				}
			}
			return sb.append(']').toString();
		}
	}

	public static int indexOf(Object[] array, int start, int end, Object element) {
		if (element == null) {
			for (int i = start; i < end; i++) {
				if (array[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = start; i < end; i++) {
				if (element.equals(array[i])) {
					return i;
				}
			}
		}
		return -1;
	}

	private ArrayUtils() {
	}

	public static <T> T[] copy(final T[] original) {
		return ArrayUtils.copyOf(original, original.length);
	}

	public static int[] copy(final int[] original) {
		return ArrayUtils.copyOf(original, original.length);
	}

	/**
	 * 安全复制数组.
	 *
	 * @param array T
	 * @param <T> 泛型
	 * @return T
	 */
	@SuppressWarnings("unchecked")
	public static <T> T copyArray(T array) {
		if (array == null) {
			return null;
		}

		Class clazz = array.getClass();

		if (clazz == int[].class) {
			int len = ((int[]) array).length;
			int[] result = new int[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == Integer[].class) {
			int len = ((Integer[]) array).length;
			Integer[] result = new Integer[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == long[].class) {
			int len = ((long[]) array).length;
			long[] result = new long[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == Long[].class) {
			int len = ((Long[]) array).length;
			Long[] result = new Long[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == double[].class) {
			int len = ((double[]) array).length;
			double[] result = new double[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == Double[].class) {
			int len = ((Double[]) array).length;
			Double[] result = new Double[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == String[].class) {
			int len = ((String[]) array).length;
			String[] result = new String[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else if (clazz == Date[].class) {
			int len = ((Date[]) array).length;
			Date[] result = new Date[len];
			System.arraycopy(array, 0, result, 0, len);

			return (T) result;
		} else {
			throw new UnsupportedOperationException("unimplemented: " + clazz);
		}
	}

	/**
	 * <p>Returns the length of the specified array.
	 * This method can deal with <code>Object</code> arrays and with primitive arrays.</p>
	 *
	 * <p>If the input array is <code>null</code>, <code>0</code> is returned.</p>
	 *
	 * <pre>
	 * ArrayUtils.getLength(null)            = 0
	 * ArrayUtils.getLength([])              = 0
	 * ArrayUtils.getLength([null])          = 1
	 * ArrayUtils.getLength([true, false])   = 2
	 * ArrayUtils.getLength([1, 2, 3])       = 3
	 * ArrayUtils.getLength(["a", "b", "c"]) = 3
	 * </pre>
	 *
	 * @param array  the array to retrieve the length from, may be null
	 * @return The length of the array, or <code>0</code> if the array is <code>null</code>
	 * @throws IllegalArgumentException if the object arguement is not an array.
	 */
	public static int getLength(final Object array) {
		if (array == null) {
			return 0;
		} else {
			return Array.getLength(array);
		}
	}

	public static <T> int indexOf11(final T[] array, final T value) {
		final int alen = array.length;
		for (int i = 0; i < alen; i++) {
			if (value.equals(array[i])) {
				return i;
			}
		}
		return INDEX_NOT_FOUND;
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array.
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component
	 * type of the returned array is always the same as that of the input
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 *
	 * <pre>
	 * ArrayUtils.insert(null, 0, null)      = [null]
	 * ArrayUtils.insert(null, 0, "a")       = ["a"]
	 * ArrayUtils.insert(["a"], 1, null)     = ["a", null]
	 * ArrayUtils.insert(["a"], 1, "b")      = ["a", "b"]
	 * ArrayUtils.insert(["a", "b"], 3, "c") = ["a", "b", "c"]
	 * </pre>
	 *
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range
	 * (index < 0 || index > array.length).
	 */
	public static <T> T[] insert(final Object array, final int index, final Object element) {
		if (array == null) {
			if (index != 0) {
				throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
			}
			Object joinedArray = Array.newInstance(element != null ? element.getClass() : Object.class, 1);
			Array.set(joinedArray, 0, element);
			return (T[]) joinedArray;
		}
		int length = getLength(array);
		if (index > length || index < 0) {
			throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
		}
		Object result = Array.newInstance(array.getClass().getComponentType(), length + 1);
		System.arraycopy(array, 0, result, 0, index);
		Array.set(result, index, element);
		if (index < length) {
			System.arraycopy(array, index, result, index + 1, length - index);
		}
		return (T[]) result;
	}

	public static long[] insert(final long[] array, final long element) {
		long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
		newArray[lastIndex(newArray)] = element;
		return newArray;
	}

	public static long[] insert(final long[] vals, final int idx, final long val) {
		long[] newVals = new long[vals.length + 1];
		if (idx > 0) {
			System.arraycopy(vals, 0, newVals, 0, idx);
		}
		newVals[idx] = val;
		if (idx < vals.length) {
			System.arraycopy(vals, idx, newVals, idx + 1, vals.length - idx);
		}
		return newVals;
	}

	public static byte[][] insert(final byte[][] vals, final int idx, final byte[] val) {
		byte[][] newVals = new byte[vals.length + 1][];
		if (idx > 0) {
			System.arraycopy(vals, 0, newVals, 0, idx);
		}
		newVals[idx] = val;
		if (idx < vals.length) {
			System.arraycopy(vals, idx, newVals, idx + 1, vals.length - idx);
		}
		return newVals;
	}

	public static boolean containsElement(Object array[], Object element) {
		if (array == null)
			return false;
		for (int i = 0; i < array.length; i++)
			if (ObjectUtils.nullSafeEquals(array[i], element))
				return true;

		return false;
	}

	/**
	 * 用于把数组的第一个元素从其中删除，并返回第一个元素的值 如果数组是空的，
	 * 那么 shift() 方法将不进行任何操作，返回 null
	 * 值
	 * 
	 * @param a
	 * @return 数组原来的第一个元素的值
	 */
	public static Object shift(Object... a) {
		if (ArrayUtils.isEmpty(a)) {
			return null;
		}
		Object t = a[0];
		remove(a, 0);
		return t;
	}

	/**
	 * Rearranges the array items in random order using the default
	 * java.util.Random generator. Operation is in-place, no copy is created.
	 * 
	 * @param array
	 * @return 
	 */
	public static <T> void shuffleT(T[] array) {
		shuffle(array, new Random());
	}

	/**
	 * Rearranges the array items in random order using the given RNG. Operation
	 * is in-place, no copy is created.
	 * 
	 * @param array
	 * @param rnd
	 */
	public static <T> void shuffle(T[] array, Random rnd) {
		int N = array.length;
		for (int i = 0; i < N; i++) {
			int r = i + (int) (rnd.nextFloat() * (N - i)); // between i and N-1
			T swap = array[i];
			array[i] = array[r];
			array[r] = swap;
		}
	}

	/**
	 * Add new value to exsisting array.The new value is indexed to the last.
	 * 
	 * @param <T>
	 * @param current
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] add(T[] current, T value) {
		// Assertion.notNull(current);
		T[] newone = (T[]) Array.newInstance(current.getClass().getComponentType(), current.length + 1);
		copyAll(current, newone);
		newone[current.length] = value;
		return newone;
	}

	/**
	 * Add new value, which sets as the first value, to existing array.
	 * 
	 * @param <T>
	 * @param current
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] addFirst(T[] current, T value) {
		// Assertion.notNull(current);
		T[] newone = (T[]) Array.newInstance(current.getClass().getComponentType(), current.length + 1);
		copy(current, newone, 0, 1, current.length);
		newone[0] = value;
		return newone;
	}

	/**
	 * Add array.
	 * 
	 * @param <T>
	 * @param from
	 * @param to
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] addAll(T[] from, T[] to) {
		// Assertion.notNulls(from, to);
		T[] newone = (T[]) Array.newInstance(from.getClass().getComponentType(), from.length + to.length);
		copyAll(from, newone);
		copy(to, newone, 0, from.length, to.length);
		return newone;
	}

	/**
	 * Copy array.
	 * 
	 * @param <T>
	 * @param from
	 * @param to
	 * @return
	 */
	public static <T> T[] copyAll(T[] from, T[] to) {
		System.arraycopy(from, 0, to, 0, from.length);
		return to;
	}

	/**
	 * Copy array with from and to position.
	 * 
	 * @param <T>
	 * @param from
	 * @param to
	 * @param fromPos
	 * @param toPos
	 * @param length
	 * @return
	 */
	public static <T> T[] copy(T[] from, T[] to, int fromPos, int toPos, int length) {
		System.arraycopy(from, fromPos, to, toPos, length);
		return to;
	}

	/**
	 * Return true if the array contains the element.
	 * 
	 * @param <T>
	 * @param array
	 * @param element
	 * @return
	 */
	public static <T> boolean containsT(T[] array, T element) {
		if (array == null || element == null) {
			return false;
		}
		for (T t : array) {
			if (element.equals(t)) {
				return true;
			}
		}
		return false;
	}

	/**
	* 使用一个新大小重设数组，并拷贝旧数组的内容到新数组
	* @param oldArray  旧数组被重设
	* @param newSize   新数组大小
	* @return          返回带同样内容的新数组
	*/
	@SuppressWarnings("unchecked")
	public static Object resize(int newSize, Object oldArray) {
		int oldSize = java.lang.reflect.Array.getLength(oldArray);

		Object newArray = Array.newInstance(oldArray.getClass().getComponentType(), newSize);

		int preserveLength = Math.min(oldSize, newSize);

		if (preserveLength > 0)
			System.arraycopy(oldArray, 0, newArray, 0, preserveLength);

		return newArray;
	}

	public static <T> T[] expand(T[] in) {
		return null;//resize(in,(in.length * 3 / 2));
	}

	// Clone
	//-----------------------------------------------------------------------
	/**
	 * <p>Shallow clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>The objects in the array are not cloned, thus there is no special
	 * handling for multi-dimensional arrays.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to shallow clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static Object[] clone(Object[] array) {
		if (array == null) {
			return null;
		}
		return (Object[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static long[] clone(long[] array) {
		if (array == null) {
			return null;
		}
		return (long[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static int[] clone(int[] array) {
		if (array == null) {
			return null;
		}
		return (int[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static short[] clone(short[] array) {
		if (array == null) {
			return null;
		}
		return (short[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static char[] clone(char[] array) {
		if (array == null) {
			return null;
		}
		return (char[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static byte[] clone(byte[] array) {
		if (array == null) {
			return null;
		}
		return (byte[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static double[] clone(double[] array) {
		if (array == null) {
			return null;
		}
		return (double[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static float[] clone(float[] array) {
		if (array == null) {
			return null;
		}
		return (float[]) array.clone();
	}

	/**
	 * <p>Clones an array returning a typecast result and handling
	 * <code>null</code>.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  the array to clone, may be <code>null</code>
	 * @return the cloned array, <code>null</code> if <code>null</code> input
	 */
	public static boolean[] clone(boolean[] array) {
		if (array == null) {
			return null;
		}
		return (boolean[]) array.clone();
	}

	// Subarrays
	//-----------------------------------------------------------------------
	/**
	 * <p>Produces a new array containing the elements between
	 * the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * <p>The component type of the subarray is always the same as
	 * that of the input array. Thus, if the input is an array of type
	 * <code>Date</code>, the following usage is envisaged:</p>
	 *
	 * <pre>
	 * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
	 * </pre>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static Object[] subarray(Object[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		Class type = array.getClass().getComponentType();
		if (newSize <= 0) {
			return (Object[]) Array.newInstance(type, 0);
		}
		Object[] subarray = (Object[]) Array.newInstance(type, newSize);
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>long</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static long[] subarray(long[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_LONG_ARRAY;
		}

		long[] subarray = new long[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>int</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static int[] subarray(int[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_INT_ARRAY;
		}

		int[] subarray = new int[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>short</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static short[] subarray(short[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_SHORT_ARRAY;
		}

		short[] subarray = new short[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>char</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static char[] subarray(char[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_CHAR_ARRAY;
		}

		char[] subarray = new char[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>byte</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_BYTE_ARRAY;
		}

		byte[] subarray = new byte[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>double</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static double[] subarray(double[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_DOUBLE_ARRAY;
		}

		double[] subarray = new double[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>float</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static float[] subarray(float[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_FLOAT_ARRAY;
		}

		float[] subarray = new float[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Produces a new <code>boolean</code> array containing the elements
	 * between the start and end indices.</p>
	 *
	 * <p>The start index is inclusive, the end index exclusive.
	 * Null array input produces null output.</p>
	 *
	 * @param array  the array
	 * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
	 *      is promoted to 0, overvalue (&gt;array.length) results
	 *      in an empty array.
	 * @param endIndexExclusive  elements up to endIndex-1 are present in the
	 *      returned subarray. Undervalue (&lt; startIndex) produces
	 *      empty array, overvalue (&gt;array.length) is demoted to
	 *      array length.
	 * @return a new array containing the elements between
	 *      the start and end indices.
	 * @since 2.1
	 */
	public static boolean[] subarray(boolean[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;
		if (newSize <= 0) {
			return EMPTY_BOOLEAN_ARRAY;
		}

		boolean[] subarray = new boolean[newSize];
		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
		return subarray;
	}

	/**
	 * <p>Checks whether two arrays are the same type taking into account
	 * multi-dimensional arrays.</p>
	 * 
	 * @param array1 the first array, must not be <code>null</code>
	 * @param array2 the second array, must not be <code>null</code>
	 * @return <code>true</code> if type of arrays matches
	 * @throws IllegalArgumentException if either array is <code>null</code>
	 */
	public static boolean isSameType(Object array1, Object array2) {
		if (array1 == null || array2 == null) {
			throw new IllegalArgumentException("The Array must not be null");
		}
		return array1.getClass().getName().equals(array2.getClass().getName());
	}

	// Primitive/Object array converters
	// ----------------------------------------------------------------------

	// Character array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Characters to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Character</code> array, may be <code>null</code>
	 * @return a <code>char</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static char[] toPrimitive(Character[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_CHAR_ARRAY;
		}
		final char[] result = new char[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].charValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Character to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Character</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>char</code> array, <code>null</code> if null array input
	 */
	public static char[] toPrimitive(Character[] array, char valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_CHAR_ARRAY;
		}
		final char[] result = new char[array.length];
		for (int i = 0; i < array.length; i++) {
			Character b = array[i];
			result[i] = (b == null ? valueForNull : b.charValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive chars to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array a <code>char</code> array
	 * @return a <code>Character</code> array, <code>null</code> if null array input
	 */
	public static Character[] toObject(char[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_CHARACTER_OBJECT_ARRAY;
		}
		final Character[] result = new Character[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Character(array[i]);
		}
		return result;
	}

	// Long array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Longs to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Long</code> array, may be <code>null</code>
	 * @return a <code>long</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static long[] toPrimitive(Long[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_LONG_ARRAY;
		}
		final long[] result = new long[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].longValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Long to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Long</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>long</code> array, <code>null</code> if null array input
	 */
	public static long[] toPrimitive(Long[] array, long valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_LONG_ARRAY;
		}
		final long[] result = new long[array.length];
		for (int i = 0; i < array.length; i++) {
			Long b = array[i];
			result[i] = (b == null ? valueForNull : b.longValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive longs to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>long</code> array
	 * @return a <code>Long</code> array, <code>null</code> if null array input
	 */
	public static Long[] toObject(long[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_LONG_OBJECT_ARRAY;
		}
		final Long[] result = new Long[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Long(array[i]);
		}
		return result;
	}

	// Int array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Integers to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Integer</code> array, may be <code>null</code>
	 * @return an <code>int</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static int[] toPrimitive(Integer[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_INT_ARRAY;
		}
		final int[] result = new int[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].intValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Integer to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Integer</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return an <code>int</code> array, <code>null</code> if null array input
	 */
	public static int[] toPrimitive(Integer[] array, int valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_INT_ARRAY;
		}
		final int[] result = new int[array.length];
		for (int i = 0; i < array.length; i++) {
			Integer b = array[i];
			result[i] = (b == null ? valueForNull : b.intValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive ints to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  an <code>int</code> array
	 * @return an <code>Integer</code> array, <code>null</code> if null array input
	 */
	public static Integer[] toObject(int[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_INTEGER_OBJECT_ARRAY;
		}
		final Integer[] result = new Integer[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Integer(array[i]);
		}
		return result;
	}

	// Short array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Shorts to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Short</code> array, may be <code>null</code>
	 * @return a <code>byte</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static short[] toPrimitive(Short[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_SHORT_ARRAY;
		}
		final short[] result = new short[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].shortValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Short to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Short</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>byte</code> array, <code>null</code> if null array input
	 */
	public static short[] toPrimitive(Short[] array, short valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_SHORT_ARRAY;
		}
		final short[] result = new short[array.length];
		for (int i = 0; i < array.length; i++) {
			Short b = array[i];
			result[i] = (b == null ? valueForNull : b.shortValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive shorts to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>short</code> array
	 * @return a <code>Short</code> array, <code>null</code> if null array input
	 */
	public static Short[] toObject(short[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_SHORT_OBJECT_ARRAY;
		}
		final Short[] result = new Short[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Short(array[i]);
		}
		return result;
	}

	// Byte array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Bytes to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Byte</code> array, may be <code>null</code>
	 * @return a <code>byte</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static byte[] toPrimitive(Byte[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BYTE_ARRAY;
		}
		final byte[] result = new byte[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].byteValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Bytes to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Byte</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>byte</code> array, <code>null</code> if null array input
	 */
	public static byte[] toPrimitive(Byte[] array, byte valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BYTE_ARRAY;
		}
		final byte[] result = new byte[array.length];
		for (int i = 0; i < array.length; i++) {
			Byte b = array[i];
			result[i] = (b == null ? valueForNull : b.byteValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive bytes to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>byte</code> array
	 * @return a <code>Byte</code> array, <code>null</code> if null array input
	 */
	public static Byte[] toObject(byte[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BYTE_OBJECT_ARRAY;
		}
		final Byte[] result = new Byte[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Byte(array[i]);
		}
		return result;
	}

	// Double array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Doubles to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Double</code> array, may be <code>null</code>
	 * @return a <code>double</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static double[] toPrimitive(Double[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_DOUBLE_ARRAY;
		}
		final double[] result = new double[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].doubleValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Doubles to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Double</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>double</code> array, <code>null</code> if null array input
	 */
	public static double[] toPrimitive(Double[] array, double valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_DOUBLE_ARRAY;
		}
		final double[] result = new double[array.length];
		for (int i = 0; i < array.length; i++) {
			Double b = array[i];
			result[i] = (b == null ? valueForNull : b.doubleValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive doubles to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>double</code> array
	 * @return a <code>Double</code> array, <code>null</code> if null array input
	 */
	public static Double[] toObject(double[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_DOUBLE_OBJECT_ARRAY;
		}
		final Double[] result = new Double[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Double(array[i]);
		}
		return result;
	}

	//   Float array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Floats to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Float</code> array, may be <code>null</code>
	 * @return a <code>float</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static float[] toPrimitive(Float[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_FLOAT_ARRAY;
		}
		final float[] result = new float[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].floatValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Floats to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Float</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>float</code> array, <code>null</code> if null array input
	 */
	public static float[] toPrimitive(Float[] array, float valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_FLOAT_ARRAY;
		}
		final float[] result = new float[array.length];
		for (int i = 0; i < array.length; i++) {
			Float b = array[i];
			result[i] = (b == null ? valueForNull : b.floatValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive floats to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>float</code> array
	 * @return a <code>Float</code> array, <code>null</code> if null array input
	 */
	public static Float[] toObject(float[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_FLOAT_OBJECT_ARRAY;
		}
		final Float[] result = new Float[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = new Float(array[i]);
		}
		return result;
	}

	// Boolean array converters
	// ----------------------------------------------------------------------
	/**
	 * <p>Converts an array of object Booleans to primitives.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Boolean</code> array, may be <code>null</code>
	 * @return a <code>boolean</code> array, <code>null</code> if null array input
	 * @throws NullPointerException if array content is <code>null</code>
	 */
	public static boolean[] toPrimitive(Boolean[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BOOLEAN_ARRAY;
		}
		final boolean[] result = new boolean[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = array[i].booleanValue();
		}
		return result;
	}

	/**
	 * <p>Converts an array of object Booleans to primitives handling <code>null</code>.</p>
	 * 
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>Boolean</code> array, may be <code>null</code>
	 * @param valueForNull  the value to insert if <code>null</code> found
	 * @return a <code>boolean</code> array, <code>null</code> if null array input
	 */
	public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BOOLEAN_ARRAY;
		}
		final boolean[] result = new boolean[array.length];
		for (int i = 0; i < array.length; i++) {
			Boolean b = array[i];
			result[i] = (b == null ? valueForNull : b.booleanValue());
		}
		return result;
	}

	/**
	 * <p>Converts an array of primitive booleans to objects.</p>
	 *
	 * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
	 * 
	 * @param array  a <code>boolean</code> array
	 * @return a <code>Boolean</code> array, <code>null</code> if null array input
	 */
	public static Boolean[] toObject(boolean[] array) {
		if (array == null) {
			return null;
		} else if (array.length == 0) {
			return EMPTY_BOOLEAN_OBJECT_ARRAY;
		}
		final Boolean[] result = new Boolean[array.length];
		for (int i = 0; i < array.length; i++) {
			result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
		}
		return result;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new boolean[] array.
	 * @since 2.1
	 */
	public static boolean[] addAll(boolean[] array1, boolean[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		boolean[] joinedArray = new boolean[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new char[] array.
	 * @since 2.1
	 */
	public static char[] addAll(char[] array1, char[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		char[] joinedArray = new char[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new byte[] array.
	 * @since 2.1
	 */
	public static byte[] addAll(byte[] array1, byte[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		byte[] joinedArray = new byte[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new short[] array.
	 * @since 2.1
	 */
	public static short[] addAll(short[] array1, short[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		short[] joinedArray = new short[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new int[] array.
	 * @since 2.1
	 */
	public static int[] addAll(int[] array1, int[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		int[] joinedArray = new int[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new long[] array.
	 * @since 2.1
	 */
	public static long[] addAll(long[] array1, long[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		long[] joinedArray = new long[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new float[] array.
	 * @since 2.1
	 */
	public static float[] addAll(float[] array1, float[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		float[] joinedArray = new float[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Adds all the elements of the given arrays into a new array.</p>
	 * <p>The new array contains all of the element of <code>array1</code> followed
	 * by all of the elements <code>array2</code>. When an array is returned, it is always
	 * a new array.</p>
	 *
	 * <pre>
	 * ArrayUtils.addAll(array1, null)   = cloned copy of array1
	 * ArrayUtils.addAll(null, array2)   = cloned copy of array2
	 * ArrayUtils.addAll([], [])         = []
	 * </pre>
	 *
	 * @param array1  the first array whose elements are added to the new array.
	 * @param array2  the second array whose elements are added to the new array.
	 * @return The new double[] array.
	 * @since 2.1
	 */
	public static double[] addAll(double[] array1, double[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		double[] joinedArray = new double[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0)   = [0]
	 * ArrayUtils.add([1], 0)    = [1, 0]
	 * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static byte[] add(byte[] array, byte element) {
		byte[] newArray = (byte[]) copyArrayGrow1(array, Byte.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, '0')       = ['0']
	 * ArrayUtils.add(['1'], '0')      = ['1', '0']
	 * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static char[] add(char[] array, char element) {
		char[] newArray = (char[]) copyArrayGrow1(array, Character.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0)   = [0]
	 * ArrayUtils.add([1], 0)    = [1, 0]
	 * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static double[] add(double[] array, double element) {
		double[] newArray = (double[]) copyArrayGrow1(array, Double.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0)   = [0]
	 * ArrayUtils.add([1], 0)    = [1, 0]
	 * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static float[] add(float[] array, float element) {
		float[] newArray = (float[]) copyArrayGrow1(array, Float.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0)   = [0]
	 * ArrayUtils.add([1], 0)    = [1, 0]
	 * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static long[] add(long[] array, long element) {
		long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/**
	 * <p>Copies the given array and adds the given element at the end of the new array.</p>
	 *
	 * <p>The new array contains the same elements of the input
	 * array plus the given element in the last position. The component type of 
	 * the new array is the same as that of the input array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0)   = [0]
	 * ArrayUtils.add([1], 0)    = [1, 0]
	 * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
	 * </pre>
	 * 
	 * @param array  the array to copy and add the element to, may be <code>null</code>
	 * @param element  the object to add at the last index of the new array
	 * @return A new array containing the existing elements plus the new element
	 * @since 2.1
	 */
	public static short[] add(short[] array, short element) {
		short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	public static <T> T[] deleteArray(T[] items, int index) {
		if (items == null || items.length == 0 || index < 0 || index > items.length - 1) {
			return items;
		}
		T[] newItems = (T[]) Array.newInstance(items.getClass().getComponentType(), items.length - 1);
		if (index == 0) {
			// first
			System.arraycopy(items, 1, newItems, 0, newItems.length);
		} else if (index == items.length - 1) {
			// end
			System.arraycopy(items, 0, newItems, 0, newItems.length);
		} else {
			// middle
			System.arraycopy(items, 0, newItems, 0, index);
			System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
		}

		return newItems;

	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0, null)      = [null]
	 * ArrayUtils.add(null, 0, "a")       = ["a"]
	 * ArrayUtils.add(["a"], 1, null)     = ["a", null]
	 * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
	 * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static Object[] add(Object[] array, int index, Object element) {
		Class clss = null;
		if (array != null) {
			clss = array.getClass().getComponentType();
		} else if (element != null) {
			clss = element.getClass();
		} else {
			return new Object[] { null };
		}
		return (Object[]) add(array, index, element, clss);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0, true)          = [true]
	 * ArrayUtils.add([true], 0, false)       = [false, true]
	 * ArrayUtils.add([false], 1, true)       = [false, true]
	 * ArrayUtils.add([true, false], 1, true) = [true, true, false]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static boolean[] add(boolean[] array, int index, boolean element) {
		return (boolean[]) add(array, index, BooleanUtils.toBooleanObject(element), Boolean.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add(null, 0, 'a')            = ['a']
	 * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
	 * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
	 * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
	 * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static char[] add(char[] array, int index, char element) {
		return (char[]) add(array, index, new Character(element), Character.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1], 0, 2)         = [2, 1]
	 * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
	 * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
	 * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static byte[] add(byte[] array, int index, byte element) {
		return (byte[]) add(array, index, new Byte(element), Byte.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1], 0, 2)         = [2, 1]
	 * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
	 * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
	 * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static short[] add(short[] array, int index, short element) {
		return (short[]) add(array, index, new Short(element), Short.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1], 0, 2)         = [2, 1]
	 * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
	 * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
	 * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static int[] add(int[] array, int index, int element) {
		return (int[]) add(array, index, new Integer(element), Integer.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
	 * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
	 * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
	 * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static long[] add(long[] array, int index, long element) {
		return (long[]) add(array, index, new Long(element), Long.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
	 * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
	 * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
	 * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static float[] add(float[] array, int index, float element) {
		return (float[]) add(array, index, new Float(element), Float.TYPE);
	}

	/**
	 * <p>Inserts the specified element at the specified position in the array. 
	 * Shifts the element currently at that position (if any) and any subsequent
	 * elements to the right (adds one to their indices).</p>
	 *
	 * <p>This method returns a new array with the same elements of the input
	 * array plus the given element on the specified position. The component 
	 * type of the returned array is always the same as that of the input 
	 * array.</p>
	 *
	 * <p>If the input array is <code>null</code>, a new one element array is returned
	 *  whose component type is the same as the element.</p>
	 * 
	 * <pre>
	 * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
	 * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
	 * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
	 * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
	 * </pre>
	 * 
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @return A new array containing the existing elements and the new element
	 * @throws IndexOutOfBoundsException if the index is out of range 
	 * (index < 0 || index > array.length).
	 */
	public static double[] add(double[] array, int index, double element) {
		return (double[]) add(array, index, new Double(element), Double.TYPE);
	}

	/**
	 * Underlying implementation of add(array, index, element) methods. 
	 * The last parameter is the class, which may not equal element.getClass 
	 * for primitives.
	 *
	 * @param array  the array to add the element to, may be <code>null</code>
	 * @param index  the position of the new object
	 * @param element  the object to add
	 * @param clss the type of the element being added
	 * @return A new array containing the existing elements and the new element
	 */
	private static Object add(Object array, int index, Object element, Class clss) {
		if (array == null) {
			if (index != 0) {
				throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
			}
			Object joinedArray = Array.newInstance(clss, 1);
			Array.set(joinedArray, 0, element);
			return joinedArray;
		}
		int length = Array.getLength(array);
		if (index > length || index < 0) {
			throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
		}
		Object result = Array.newInstance(clss, length + 1);
		System.arraycopy(array, 0, result, 0, index);
		Array.set(result, index, element);
		if (index < length) {
			System.arraycopy(array, index, result, index + 1, length - index);
		}
		return result;
	}

	public static <T> int countValues(T[] array, T t) {
		int count = 0;
		for (T tmp : array) {
			if (ObjectUtils.equals(tmp, t))
				count++;
		}
		return count;
	}

	public static int countValues(int[] array, int t) {
		int count = 0;
		for (int tmp : array) {
			if (tmp == t)
				count++;
		}
		return count;
	}

	public static int countValues(String[] array, String t, boolean ignoreCase) {
		int count = 0;
		if (ignoreCase)
			for (String tmp : array) {
				if (StringUtils.equalsIgnoreCase(tmp, t))
					count++;
			}
		else
			for (String tmp : array) {
				if (StringUtils.equals(tmp, t))
					count++;
			}
		return count;
	}

	public static int countValues(long[] array, long t) {
		int count = 0;
		for (long tmp : array) {
			if (tmp == t)
				count++;
		}
		return count;
	}

	public static int[] createArray(int begin, int end) {
		int[] tmp = new int[end - begin + 1];
		for (int i = 0; begin <= end; begin++, i++)
			tmp[i] = begin;
		return tmp;

	}

	public static long[] createArray(long begin, long end) {
		int size = Convert.toInt(end - begin + 1L);
		long[] tmp = new long[size];
		for (int i = 0; begin <= end; begin++, i++)
			tmp[i] = begin;
		return tmp;

	}

	public static double[][] array2Matrix(double[] data, int nRow, int nCol) {

		if ((nRow * nCol) != data.length) {
			throw new RuntimeException("array2Matrix(): nRow*nCol must be equal to data.length");
		}
		double[][] res = new double[nRow][nCol];

		int index = 0;
		for (int j = 0; j < nCol; j++) {
			for (int i = 0; i < nRow; i++) {
				res[i][j] = data[index];
				index++;
			}
		}

		return res;
	}

	/**
	 * Compare two 2-d arrays and show the differences. It prints nothing if the
	 * 2-d arrays are equal.
	 *
	 * @param a
	 *            The first 2-d array
	 * @param b
	 *            The second 2-d array
	 *
	 * @return <tt>true</tt>, if they are equal
	 */
	static public void compare(double[][] a, double[][] b) {
		if (a == null) {
			System.out.println("A is null");
			return;
		}

		if (b == null) {
			System.out.println("B is null");
			return;
		}

		int nrows = a.length;
		if (b.length != nrows) {
			System.out.println("A has " + nrows + " rows, while B " + b.length);
		}

		int ncols = a[0].length;
		if (b[0].length != ncols) {
			System.out.println("A has " + nrows + " columns, while B " + b.length);
		}

		for (int i = 0; i < nrows; i++) {
			for (int j = 0; j < ncols; j++) {
				if (a[i][j] != b[i][j]) {
					System.out.printf("Element[%d][%d]: A has %.5f while B %.5f\n", i, j, a[i][j], b[i][j]);
				}
			}
		}
	}

	/**
	 * Returns the Type of an array. For example if <tt>array</tt> is am
	 * instance of String[], the class String will be returned.
	 *
	 * @param <T>
	 * @param array
	 *            An one-dimension array
	 * @return The array type
	 */
	static public <T> Class<?> getClass(T[] array) {
		return array.getClass().getComponentType();
	}

	/**
	 * Returns the Type of an 2D array. For example if <tt>array</tt> is am
	 * instance of String[][], the class String will be returned.
	 *
	 * @param <T>
	 * @param array
	 *            An bi-dimensional array
	 * @return The array type
	 */
	static public <T> Class<?> getClass(T[][] array) {
		return array.getClass().getComponentType().getComponentType();
	}

	static public double[] copy(double[] d) {
		if (d == null) {
			return null;
		}
		return Arrays.copyOf(d, d.length);
	}

	static public String[] copy(String[] s) {
		if (s == null) {
			return null;
		}
		return Arrays.copyOf(s, s.length);
	}

	/**
	 * Test if two 2-d arrays are equal
	 *
	 * @param a
	 *            The first 2-d array
	 * @param b
	 *            The second 2-d array
	 *
	 * @return <tt>true</tt>, if they are equal
	 */
	static public boolean equals(double[][] a, double[][] b) {
		return equals(a, b, 0);
	}

	/**
	 * Test if two 2-d arrays are equal
	 *
	 * @param a
	 *            The first 2-d array
	 * @param b
	 *            The second 2-d array
	 * @param tollerance
	 *            The absolute difference under which two value are considered
	 *            equal.
	 *
	 * @return <tt>true</tt>, if they are equal
	 */
	static public boolean equals(double[][] a, double[][] b, double tollerance) {
		if (a == b) {
			return true;
		}

		if (a == null || b == null) {
			return false;
		}

		int nrows = a.length;
		if (b.length != nrows) {
			return false;
		}

		int ncols = a[0].length;
		if (b[0].length != ncols) {
			return false;
		}

		for (int i = 0; i < nrows; i++) {
			for (int j = 0; j < ncols; j++) {
				double absDiff = Math.abs(a[i][j] - b[i][j]);
				if (absDiff < tollerance) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Test if an array contains no duplicate elements.
	 *
	 * @param names
	 * @return
	 */
	static public <E> boolean isSet(E[] values) {
		Set<E> set = new HashSet<E>();
		for (E elem : values) {
			set.add(elem);
		}

		return set.size() == values.length;
	}

	public static double[] matrix2Array(double[][] data) {
		int nRow = data.length;
		int nCol = data[0].length;
		double[] res = new double[nRow * nCol];

		int index = 0;
		for (int j = 0; j < nCol; j++) {
			for (int i = 0; i < nRow; i++) {
				res[index] = data[i][j];
				index++;
			}
		}

		return res;
	}

	public static String matrixToString(double[][] m) {
		return matrixToString(m, 5, null, null);
	}

	// TODO test
	public static String matrixToString(double[][] m, int d, String[] rownames, String[] colnames) {
		int n1 = m.length;
		int n2 = m[0].length;
		int max = 0;
		StringBuffer sb = new StringBuffer();

		if (rownames != null) {
			for (int i = 0; i < rownames.length; i++) {
				max = Math.max(max, rownames[i].length());
			}

			if (rownames.length != n1) {
				throw new IllegalArgumentException("The number of rows doesn't correspond");
			}
		}

		// Determina w (spaziatura prima dei numeri)
		int w = 1;
		for (int i = 0; i < n1; i++) {
			for (int j = 0; j < n2; j++) {
				String sm = "" + m[i][j];
				w = Math.max(w, sm.indexOf("."));
			}
		}
		w = w + d; // - 1;

		// Some definitions for handling output formating
		NumberFormat myFormat = NumberFormat.getNumberInstance();
		FieldPosition fp = new FieldPosition(NumberFormat.INTEGER_FIELD);
		// myFormat.setMaximumIntegerDigits(d);
		myFormat.setMaximumFractionDigits(d);
		myFormat.setMinimumFractionDigits(d);

		int[] wcol = new int[n2];
		// Stampa e formatta i titoli delle colonne
		if (colnames != null) {

			for (int i = 0; i < colnames.length; i++) {
				wcol[i] = colnames[i].length();
			}

			if (colnames.length != n2) {
				throw new IllegalArgumentException("The number of columnnames (" + colnames.length
						+ ") doesn't correspond. It was expected " + n2);
			}

			sb.append(StringUtils.line(' ', max + Math.max(w, wcol[0]) - colnames[0].length() + d + 1) + colnames[0]);
			for (int j = 1; j < n2; j++) {
				sb.append(StringUtils.line(' ', Math.max(w, wcol[j]) - colnames[j].length() + d + 1) + colnames[j]);
			}
			sb.append("\n");
		}

		String valString;
		for (int i = 0; i < n1; i++) {
			// Stampa il nome della riga
			if (rownames != null) {
				sb.append(rownames[i] + StringUtils.line(' ', max - rownames[i].length()));
			}
			// Print each row, elements separated by spaces
			for (int j = 0; j < n2; j++) {
				valString = myFormat.format(m[i][j], new StringBuffer(), fp).toString();
				// System.out.print("w="+w+" wcol["+j+"]="+wcol[j]+"
				// fp="+fp.getEndIndex());
				valString = StringUtils.line(' ', Math.max(w, wcol[j]) - fp.getEndIndex()) + valString;
				sb.append(valString);
			}
			// Start a new line at the end of a row
			sb.append("\n");
		}
		// Leave a gap after the entire matrix
		sb.append("\n");

		return sb.toString();
	}

	public static String matrixToString(int[][] m) {
		StringBuffer sb = new StringBuffer();
		int n1 = m.length;
		int n2 = m[0].length;
		int[] w = new int[n2];
		for (int j = 0; j < n2; j++) {
			w[j] = String.valueOf(m[0][j]).length();
			for (int i = 0; i < n1; i++) {
				w[j] = Math.max(w[j], (String.valueOf(m[i][j]).length()));
			}
		}

		for (int i = 0; i < n1; i++) {
			// Print each row, elements separated by spaces
			for (int j = 0; j < n2; j++) {
				String valString = String.valueOf(m[i][j]);
				valString = StringUtils.line(' ', w[j] - valString.length() + 2) + valString;
				sb.append(valString);
			}
			// Start a new line at the end of a row
			sb.append("\n");
		}
		// Leave a gap after the entire matrix
		sb.append("\n");

		return sb.toString();
	}

	public static String matrixToString(Object[][] data) {
		StringBuilder sb = new StringBuilder();
		int nrows = data.length;
		int ncols = data[0].length;

		final String NL = "\n";
		final String SEP = " ";
		for (int i = 0; i < nrows; i++) {
			for (int j = 0; j < ncols; j++) {
				sb.append(data[i][j]);
				if (j != ncols - 1) {
					sb.append(SEP);
				}
			}
			sb.append(NL);
		}

		return sb.toString();
	}

	/**
	 *
	 * Create a Java code for the 2D array
	 */
	static public String toJavaCode(double[][] m) {
		int nrows = m.length;
		int ncols = m[0].length;

		StringBuilder sb = new StringBuilder("double[][] m = { //Matrix " + nrows + " x " + ncols + "\n");

		for (int i = 0; i < nrows; i++) {
			sb.append("{");
			for (int j = 0; j < ncols; j++) {
				sb.append(m[i][j]);
				if (j < (ncols - 1)) {
					sb.append(", ");
				}
			}
			if (i < (nrows - 1)) {
				sb.append("}, //Row " + i + "\n");
			} else {
				sb.append("} //Row " + i + "\n");
			}

		}
		sb.append("};");
		return sb.toString();
	}

	static public String toJavaCode(int[][] x) {
		int nrows = x.length;
		int ncols = x[0].length;

		StringBuilder sb = new StringBuilder("double[][] m = { //Matrix " + nrows + " x " + ncols + "\n");

		for (int i = 0; i < nrows; i++) {
			sb.append("{");
			for (int j = 0; j < ncols; j++) {
				sb.append(x[i][j]);
				if (j < (ncols - 1)) {
					sb.append(", ");
				}
			}
			if (i < (nrows - 1)) {
				sb.append("}, //Row " + i + "\n");
			} else {
				sb.append("} //Row " + i + "\n");
			}

		}
		sb.append("};");
		return sb.toString();
	}

	/**
	 *
	 * Create a Java code for the array
	 */
	static public String toJavaCode(double[] array) {
		int n = array.length;

		StringBuilder sb = new StringBuilder("double[] array = {");

		for (int i = 0; i < n; i++) {
			sb.append(array[i]);
			if (i < (n - 1)) {
				sb.append(", ");
			}
		}
		sb.append("};");

		return sb.toString();
	}

	/**
	 *
	 * Create a Java code for the array
	 */
	static public String toJavaCode(int[] array) {
		int n = array.length;

		StringBuilder sb = new StringBuilder("int[] array = {");

		for (int i = 0; i < n; i++) {
			sb.append(array[i]);
			if (i < (n - 1)) {
				sb.append(", ");
			}
		}
		sb.append("};");

		return sb.toString();
	}

	/**
	 * Sorts the specified range of the specified array of longs into
	 * ascending/descending numerical order. Based on
	 * {@link Arrays#sort(double[])}, but it doesn't modify the input-array.
	 *
	 * @param asc
	 *            <tt>true</> for ascending, <tt>false</> for descending order
	 * @param x
	 *            The array to sort
	 * @return The sorted array
	 */
	static public double[] sort(double[] x, boolean asc) {
		double[] xCopy = copy(x);
		Arrays.sort(xCopy);

		if (asc) {
			return xCopy;
		} else {
			return inverse(xCopy);
		}
	}

	/**
	 * Given an array, returns a new one with inverse order.
	 *
	 * @param x
	 *            The array to invert
	 * @return The inverted array
	 */
	static public double[] inverse(double[] x) {
		int len = x.length;
		double[] res = new double[len];
		int lastindex = len - 1;
		for (double d : x) {
			res[lastindex] = d;
			lastindex--;
		}

		return res;
	}

	/**
	 * Sorts the specified two-dimension array of doubles
	 *
	 * @param x
	 *            the two-dimension array to be sorted
	 * @param col
	 *            sort the data according to column #
	 * @param asc
	 *            if <tt>true</tt>, ascending order.
	 */
	public static void sort(double x[][], int col, boolean asc) {
		sort(x, 0, x.length, col, asc);
	}

	/**
	 * Sorts the specified two-dimension array of integer
	 *
	 * @param serie
	 *            the two-dimension array to be sorted
	 * @param off
	 *            sorting beginnin from...
	 * @param len
	 *            sorting up to...
	 *@param col
	 *            sort the data according to column #
	 * @param asc
	 *            if <tt>true</tt>, ascending order.
	 */
	public static void sort(int x[][], int col, boolean asc) {
		sort(x, 0, x.length, col, asc);
	}

	/**
	 * Sorts the specified two-dimension array of double
	 *
	 * @param serie
	 *            the two-dimension array to be sorted
	 * @param off
	 *            sorting beginnin from...
	 * @param len
	 *            sorting up to...
	 *@param col
	 *            sort the data according to column #
	 * @param asc
	 *            if <tt>true</tt>, ascending order.
	 */
	public static void sort(double serie[][], int off, int len, int col, boolean asc) {
		// Insertion sort on smallest arrays
		if (len < 7) {
			for (int i = off; i < len + off; i++) {
				if (asc) {
					for (int j = i; j > off && serie[j - 1][col] > serie[j][col]; j--) {
						swap(serie, j, j - 1);
					}
				} else {
					for (int j = i; j > off && serie[j - 1][col] < serie[j][col]; j--) {
						swap(serie, j, j - 1);
					}
				}
			}
			return;
		}

		// Choose a partition element, v
		int m = off + (len >> 1); // Small arrays, middle element
		if (len > 7) {
			int l = off;
			int n = off + len - 1;
			if (len > 40) { // Big arrays, pseudomedian of 9
				int s = len / 8;
				l = med3(serie, l, l + s, l + 2 * s, col);
				m = med3(serie, m - s, m, m + s, col);
				n = med3(serie, n - 2 * s, n - s, n, col);
			}
			m = med3(serie, l, m, n, col); // Mid-size, med of 3
		}
		double v = serie[m][col];

		// Establish Invariant: v* (<v)* (>v)* v*
		int a = off, b = a, c = off + len - 1, d = c;
		if (asc) {
			while (true) {
				while (b <= c && serie[b][col] <= v) {
					if (serie[b][col] == v) {
						swap(serie, a++, b);
					}
					b++;
				}
				while (c >= b && serie[c][col] >= v) {
					if (serie[c][col] == v) {
						swap(serie, c, d--);
					}
					c--;
				}
				if (b > c) {
					break;
				}
				swap(serie, b++, c--);
			}
		} else {
			while (true) {
				while (b <= c && serie[b][col] >= v) {
					if (serie[b][col] == v) {
						swap(serie, a++, b);
					}
					b++;
				}
				while (c >= b && serie[c][col] <= v) {
					if (serie[c][col] == v) {
						swap(serie, c, d--);
					}
					c--;
				}
				if (b > c) {
					break;
				}
				swap(serie, b++, c--);
			}
		}

		// Swap partition elements back to middle
		int s, n = off + len;
		s = Math.min(a - off, b - a);
		vecswap(serie, off, b - s, s);
		s = Math.min(d - c, n - d - 1);
		vecswap(serie, b, n - s, s);

		// Recursively sort non-partition-elements
		if ((s = b - a) > 1) {
			sort(serie, off, s, col, asc);
		}
		if ((s = d - c) > 1) {
			sort(serie, n - s, s, col, asc);
		}
	}

	/**
	 * Sorts the specified two-dimension array of integer
	 *
	 * @param serie
	 *            the two-dimension array to be sorted
	 * @param off
	 *            sorting beginnin from...
	 * @param len
	 *            sorting up to...
	 *@param col
	 *            sort the data according to column #
	 * @param asc
	 *            if <tt>true</tt>, ascending order.
	 */
	public static void sort(int serie[][], int off, int len, int col, boolean asc) {
		// Converti serie da int a double
		double[][] serieDouble = new double[serie.length][serie[0].length];
		System.arraycopy(serie, 0, serieDouble, 0, serie.length);

		sort(serieDouble, off, len, col, asc);
		System.arraycopy(serieDouble, 0, serie, 0, serie.length);
	}

	/**
	 * Returns the index of the median of the three indexed integers.
	 */
	private static int med3(double serie[][], int a, int b, int c, int col) {
		return (serie[a][col] < serie[b][col] ? (serie[b][col] < serie[c][col] ? b : serie[a][col] < serie[c][col] ? c
				: a) : (serie[b][col] > serie[c][col] ? b : serie[a][col] > serie[c][col] ? c : a));
	}

	/**
	 * Swaps x[a] with x[b].
	 */

	private static void swap(double serie[][], int a, int b) {
		int ncol = serie[0].length;
		double t;
		for (int col = 0; col < ncol; col++) {
			t = serie[a][col];
			serie[a][col] = serie[b][col];
			serie[b][col] = t;
		}

	}

	/**
	 * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
	 */
	private static void vecswap(double serie[][], int a, int b, int n) {
		for (int i = 0; i < n; i++, a++, b++) {
			swap(serie, a, b);
		}
	}

	/**
	 * Transform an array to a set of unique values. The order, in which the
	 * elements appears, is preserved.
	 *
	 * @param <E>
	 * @param list
	 * @return
	 */
	static public <E> Set<E> toSet(E[] array) {
		Set<E> set = new LinkedHashSet<E>();
		for (E e : array) {
			set.add(e);
		}

		return set;
	}
	  /**
     * 联合两个数组
     *
     * @param first
     *            第一个数组
     * @param last
     *            另一个数组
     * @return 内容合并后的数组
     */
    public static Object[] combine(Object[] first, Object[] last) {
        if (first.length == 0 && last.length == 0) {
            return null;
        }
        Object[] result = new Object[first.length + last.length];
        System.arraycopy(first, 0, result, 0, first.length);
        System.arraycopy(last, 0, result, first.length, last.length);
        return result;
    }
    /**
     * 联合两个数组
     *
     * @param first
     *            第一个数组
     * @param last
     *            另一个数组
     * @return 内容合并后的数组
     */
    public static int[] combine(int[] first, int[] last) {
    	if (first.length == 0 && last.length == 0) {
    		return null;
    	}
    	int[] result = new int[first.length + last.length];
    	System.arraycopy(first, 0, result, 0, first.length);
    	System.arraycopy(last, 0, result, first.length, last.length);
    	return result;
    }
    /**
     * 清除字符串数组中的null
     *
     * @param array
     *            字符串数组
     * @return 清除null后的字符串数组
     */
    public static String[] clearNull(String[] array) {
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < array.length; i++) {
            if (array[i] != null) {
                list.add(array[i]);
            }
        }
        return toArray(list,String[].class);
    }

	public static void main(String[] args) {
		String[] s1={"1","2","3",null,"4","5","6",null}; 
	    
	    String s2[] = {"61","7","8","9"};
		 ;
	//	System.out.println(Arrays.toString(remove(s1, s1.length-1)));
		 String tmpString=null;
		 System.out.println(StringUtils.substring(tmpString, 0, StringUtils.length(tmpString)-1));
			
		
	}
}
